2008-11-27 10 views
6

इस कोडपाइथन में विंडोज़ पर stdin से डेटा पढ़ने के लिए कैसे पता लगाना है?

select.select([sys.stdin], [], [], 1.0) 

वास्तव में क्या मैं लिनक्स पर चाहते हैं करता है, लेकिन नहीं Windows में।

मैंने msvcrt में यह देखने के लिए पहले देखा है कि डेटा पढ़ने के लिए stdin पर उपलब्ध है या नहीं, लेकिन इस मामले में यह हमेशा 0 देता है। इसके अतिरिक्त msvcrt.getch()'\xff' देता है जबकि sys.stdin.read(1)'\x01' देता है। ऐसा लगता है जैसे msvcrt फ़ंक्शन ठीक से व्यवहार नहीं कर रहे हैं।

दुर्भाग्य से मैं टीसीपी सॉकेट का उपयोग नहीं कर सकता क्योंकि मैं अपने पायथन प्रोग्राम से बात करने वाले एप्लिकेशन के नियंत्रण में नहीं हूं।

उत्तर

2

कुछ दुर्लभ स्थितियों में, आप परवाह कर सकते हैं कि stdin किससे जुड़ा हुआ है। अधिकतर, आपको परवाह नहीं है - आप बस stdin पढ़ते हैं।

someprocess | python myprogram.py में, stdin एक पाइप से जुड़ा हुआ है; इस मामले में, पिछली प्रक्रिया का stdout। आप बस sys.stdin से पढ़ते हैं और आप अन्य प्रक्रिया से पढ़ रहे हैं। [ध्यान दें कि विंडोज़ में, अभी भी (संभावित रूप से) एक कीबोर्ड के साथ "CON" डिवाइस है। यह sys.stdin नहीं होगा।]

python myprogram.py <someFile में, stdin फ़ाइल से जुड़ा हुआ है। आप बस sys.stdin से पढ़ते हैं और आप फ़ाइल से पढ़ रहे हैं।

python myprogram.py में, stdin कंसोल से जुड़े हुए हैं (/dev/ttyxx * निक्स में)। आप sys.stdin से सरल पढ़ते हैं और आप कीबोर्ड से पढ़ रहे हैं।

उपर्युक्त तीन मामलों में सामान्य विषय पर ध्यान दें। आप बस sys.stdin से पढ़ते हैं और आपके प्रोग्राम का वातावरण आपके लिए सबकुछ परिभाषित करता है। आप यह देखने के लिए नहीं देखते हैं कि पढ़ने के लिए stdin पर डेटा उपलब्ध है या नहीं "। यह पहले से ही उपलब्ध है।

कभी-कभी, आप एक कीबोर्ड इंटरप्ट (या अन्य शेनानिगन्स) चाहते हैं। पायथन, बीटीडब्ल्यू, I/O तत्वों की प्रथम श्रेणी की विशेषता के रूप में एक कीबोर्ड बाधित है। कंट्रोल-सी I/O के दौरान एक बाधा उत्पन्न करता है (यह एक तंग पाश में नहीं टूट जाएगा, लेकिन यह समय-समय पर प्रिंट करने वाले प्रोग्राम को सिग्नल करेगा।)

कभी-कभी आपको यह पता लगाना होगा कि किस प्रकार की फ़ाइल stdin से जुड़ा हुआ है ।

कुछ os.isatty(sys.stdin.fileno()) की तरह कुछ sys.stdin एक टीटीवी है, तो आप प्रोग्राम "CON" (कीबोर्ड) से जुड़े हुए थे। यदि sys.stdin कोई TTY नहीं है, तो यह फ़ाइल या पाइप से जुड़ा हुआ है।


उदाहरण

Microsoft Windows XP [Version 5.1.2600] 
(C) Copyright 1985-2001 Microsoft Corp. 

C:\Documents and Settings\slott>python 
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on 
win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> import sys 
>>> os.isatty(sys.stdin.fileno()) 
True 
>>> 

True का मूल्य मुझसे कहता है अजगर एक फ़ाइल या पाइप संलग्न बिना चल रहा है। sys.stdin कीबोर्ड है। विंडोज kbhit का उपयोग करना आवश्यक नहीं है।

False का मान मुझे बताता है कि पाइथन एक फ़ाइल या पाइप संलग्न है। sys.stdin कीबोर्ड नहीं है। kbhit की जांच करना सार्थक हो सकता है।इसके अलावा, मैं CON: डिवाइस खोल सकता हूं और कीबोर्ड को सीधे पढ़ सकता हूं, sys.stdin से अलग।


मुझे यकीन नहीं है कि आपको यह देखने के लिए क्यों चाहिए कि डेटा पढ़ने के लिए stdin पर उपलब्ध है या नहीं। यह आपके प्रश्न को अतिरिक्त विवरण के साथ अपडेट करने में मदद कर सकता है जो आप पूरा करने की कोशिश कर रहे हैं।

+0

os.isatty (sys.stdin.fileno()) रिटर्न झूठी – awatts

1

मैं एक थ्रेड चलाता हूं जो stdin से पढ़ता है, फिर डेटा को सॉकेट में अग्रेषित करता है। सॉकेट चयन योग्य है, इसलिए, stdin भी चयन योग्य है।

हाल के एक प्रोजेक्ट में, मुझे लगातार एक नेटवर्क सॉकेट से पढ़ना चाहिए, एक और सॉकेट तक आगे बढ़ाना चाहिए, जब तक उपयोगकर्ता कंसोल से q इनपुट नहीं करता। कोई थ्रेडिंग का उपयोग करने के बारे में सोच सकता है, लेकिन मैं बहु-थ्रेड सामानों से निपटना नहीं चाहता हूं। अंत में, मुझे कोई स्पष्ट समाधान नहीं मिला, और यह काम किया।

मैं एक धागा बना देता हूं - हाँ, धागा, लेकिन कोई बहु-थ्रेड चिंताओं - यह थ्रेड यादृच्छिक बंदरगाह पर एक सर्वर सॉकेट सुनता है, फिर इस सर्वर से क्लाइंट सॉकेट कनेक्ट खोलें। सर्वर सॉकेट कनेक्शन स्वीकार करता है, फिर ब्लॉक तरीके से sys.stdin.read() पर कॉल करें, stdin से पढ़े गए सभी डेटा उस स्वीकृत कनेक्शन को लिखेंगे। तो क्लाइंट सॉकेट stdin से डेटा पढ़ने प्राप्त करते हैं। अब, क्लाइंट सॉकेट चयन योग्य stdin है, और यह थ्रेड-सुरक्षित है।

स्रोत कोड:

# coding=UTF-8 
""" === Windows stdio === 
@author [email protected]163.com 
@link http://www.ideawu.net/ 
File objects on Windows are not acceptable for select(), 
this module creates two sockets: stdio.s_in and stdio.s_out, 
as pseudo stdin and stdout. 

@example 
from stdio import stdio 
stdio.write('hello world') 
data = stdio.read() 
print stdio.STDIN_FILENO 
print stdio.STDOUT_FILENO 
""" 
import thread 
import sys, os 
import socket 

# socket read/write in multiple threads may cause unexpected behaviors 
# so use two separated sockets for stdin and stdout 

def __sock_stdio(): 
    def stdin_thread(sock, console): 
     """ read data from stdin, and write the data to sock 
     """ 
     try: 
      fd = sys.stdin.fileno() 
      while True: 
       # DO NOT use sys.stdin.read(), it is buffered 
       data = os.read(fd, 1024) 
       #print 'stdin read: ' + repr(data) 
       if not data: 
        break 
       while True: 
        nleft = len(data) 
        nleft -= sock.send(data) 
        if nleft == 0: 
         break 
     except: 
      pass 
     #print 'stdin_thread exit' 
     sock.close() 

    def stdout_thread(sock, console): 
     """ read data from sock, and write to stdout 
     """ 
     try: 
      fd = sys.stdout.fileno() 
      while True: 
       data = sock.recv(1024) 
       #print 'stdio_sock recv: ' + repr(data) 
       if not data: 
        break 
       while True: 
        nleft = len(data) 
        nleft -= os.write(fd, data) 
        if nleft == 0: 
         break 
     except: 
      pass 
     #print 'stdin_thread exit' 
     sock.close() 


    class Console: 
     def __init__(self): 
      self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      self.serv.bind(('127.0.0.1', 0)) 
      self.serv.listen(5) 
      port = self.serv.getsockname()[1] 

      # data read from stdin will write to this socket 
      self.stdin_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      self.stdin_sock.connect(('127.0.0.1', port)) 
      self.s_in, addr = self.serv.accept() 
      self.STDIN_FILENO = self.s_in.fileno() 
      thread.start_new_thread(stdin_thread, (self.stdin_sock, self)) 

      # data read from this socket will write to stdout 
      #self.stdout_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      #self.stdout_sock.connect(('127.0.0.1', port)) 
      #self.s_out, addr = self.serv.accept() 
      #self.STDOUT_FILENO = self.s_out.fileno() 
      #thread.start_new_thread(stdout_thread, (self.stdout_sock, self)) 

      self.read_str = '' # read buffer for readline 

     def close(self): 
      self.s_in.close() 
      self.s_out.close() 
      self.stdin_sock.close() 
      self.stdout_sock.close() 
      self.serv.close() 

     def write(self, data): 
      try: 
       return self.s_out.send(data) 
      except: 
       return -1 

     def read(self): 
      try: 
       data = self.s_in.recv(4096) 
      except: 
       return '' 
      ret = self.read_str + data 
      self.read_str = '' 
      return ret 

     def readline(self): 
      while True: 
       try: 
        data = self.s_in.recv(4096) 
       except: 
        return '' 
       if not data: 
        return '' 
       pos = data.find('\n') 
       if pos == -1: 
        self.read_str += data 
       else: 
        left = data[0 : pos + 1] 
        right = data[pos + 1 : ] 
        ret = self.read_str + left 
        self.read_str = right 
        return ret 

    stdio = Console() 
    return stdio 

def __os_stdio(): 
    class Console: 
     def __init__(self): 
      self.STDIN_FILENO = sys.stdin.fileno() 
      self.STDOUT_FILENO = sys.stdout.fileno() 

     def close(self): 
      pass 

     def write(self, data): 
      try: 
       return os.write(self.STDOUT_FILENO, data) 
      except: 
       return -1 

     def read(self): 
      try: 
       return os.read(self.STDIN_FILENO, 4096) 
      except: 
       return '' 

     def readline(self): 
      try: 
       return sys.stdin.readline() 
      except: 
       return '' 

    stdio = Console() 
    return stdio 

if os.name == 'posix': 
    stdio = __os_stdio() 
else: 
    stdio = __sock_stdio() 
+1

हाय, @Harvey संपादित करने के लिए धन्यवाद, स्रोत कोड यहाँ http: //www.ideawu .com/ब्लॉग/wp-content/अपलोड/2010/08/stdio.py_.zip – ideawu

संबंधित मुद्दे