2012-01-23 14 views
10

क्या अजगर "पर्सन" में उपप्रोसेस कॉल करने का कोई तरीका है? मैं एक प्रोग्राम को बुला रहा हूं जिसमें कई बार लोड करने में कुछ समय लगता है। तो यह बहुत अच्छा होगा अगर मैं सिर्फ उस कार्यक्रम को खोल सकता हूं और इसे मारने के बिना इसके साथ संवाद कर सकता हूं।पर्सिस्टेंट पायथन सबप्रोसेस

मेरे अजगर स्क्रिप्ट के कार्टून संस्करण इस तरह दिखता है:

for text in textcollection: 
    myprocess = subprocess.Popen(["myexecutable"], 
       stdin = subprocess.PIPE, stdout = subprocess.PIPE, 
       stderr = None) 
    myoutputtext, err = myprocess.communicate(input=text) 

मैं तो एक बड़े पाठ फ़ाइल में सभी शामिल होने और यह एक बार प्रसंस्करण प्रत्येक पाठ कार्रवाई करने के लिए की जरूरत है, एक विकल्प नहीं है।

अधिमानतः, इस

myprocess = subprocess.Popen(["myexecutable"], 
      stdin = subprocess.PIPE, stdout = subprocess.PIPE, 
      stderr = None) for text in textcollection: 
for text in textcollection: 
    myoutputtext, err = myprocess.communicate(input=text) 

जैसा कोई विकल्प जहां मैं इस प्रक्रिया को खुला छोड़ कर सकते हैं अगर, मैं वास्तव में यह सराहनीय होगा।

उत्तर

24

आप कर सकते हैं अपने सबप्रोसेस के साथ संवाद करने के लिए myprocess.stdin.write() और myprocess.stdout.read() का उपयोग करें, आपको यह सुनिश्चित करने के लिए सावधान रहना होगा कि आप अपनी कॉल को अवरुद्ध करने से रोकने के लिए सही ढंग से बफरिंग को संभालें।

यदि आपके उपप्रोसेस का आउटपुट अच्छी तरह से परिभाषित है, तो आप लाइन-बफरिंग और myprocess.stdout.readline() का उपयोग करके विश्वसनीय रूप से इसके साथ संवाद करने में सक्षम होना चाहिए।

यहाँ एक उदाहरण है:

>>> p = subprocess.Popen(['cat'], bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
>>> p.stdin.write('hello world\n') 
>>> p.stdout.readline() 
'hello world\n' 
>>> p.stdout.readline()  # THIS CALL WILL BLOCK 

यूनिक्स के लिए इस विधि के लिए एक वैकल्पिक गैर अवरुद्ध मोड में फ़ाइल संभाल रखा है, जो आप myprocess.stdout.read() जैसे कार्यों कॉल करने की अनुमति देगा और यह डेटा वापस अगर है किसी भी उपलब्ध है, या अगर कोई डेटा नहीं है एक IOError बढ़ा:

:

>>> p = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
>>> import fcntl, os 
>>> fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) 
0 
>>> p.stdout.read()   # raises an exception instead of blocking 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 11] Resource temporarily unavailable 

यह आप इस तरह कुछ करने के लिए अनुमति होगी

इस उदाहरण में, validate_output() एक ऐसा फ़ंक्शन है जिसे आपको लिखने की आवश्यकता होगी True यदि आपके द्वारा अब तक प्राप्त किया गया डेटा वह आउटपुट है जिसे आप प्राप्त करने की उम्मीद करते हैं।

+1

धन्यवाद! मुझे आपके समाधान को सबसे अच्छा पसंद है क्योंकि इसे किसी तृतीय पक्ष डाउनलोड की आवश्यकता नहीं है। दुर्भाग्य से, यह मेरे लिए काम नहीं करता है। कुछ चीजों को आजमाने के बाद, मुझे पूरा यकीन है कि यह जावा प्रोग्राम के साथ एक मुद्दा है जिसे मैं आपके समाधान के बजाय बुला रहा हूं, इसलिए आपका समाधान अच्छा है। – JasonMond

+0

नीचे वोट क्यों? –

+0

यह गलती से था। मेरा अपवर्तक निष्क्रिय है जब तक कि कुछ भी संपादित नहीं किया जाएगा, लेकिन मुझे सुधार करने या चोट पहुंचाने के लिए कुछ भी नहीं दिख रहा है। सही जवाब – hynekcer

1

मैं तुम्हें Popens की एक सूची बना सकते हैं और फिर कहते हैं एक और पाश में प्रत्येक तत्व पर बातचीत लगता है कि आप के लिए

myprocess.stdin.write(text) 

देख रहे हैं। कुछ इस

processes=[] 
for text in textcollection: 
    myprocess = subprocess.Popen(["myexecutable"], 
       stdin = subprocess.PIPE, stdout = subprocess.PIPE, 
       stderr = None) 
    myprocess.stdin.write(text) 
    processes.append(myprocess) 

for proc in processes: 
    myoutput, err=proc.communicate() 
    #do something with the output here 

की तरह इस तरह से जब तक के बाद सभी Popens

+0

दुर्भाग्यवश, यह मेरे लिए काम नहीं करेगा क्योंकि यह एक जावा प्रोग्राम है जो प्रत्येक रन पर लगभग 3 जी मेमोरी खाता है। यही कारण है कि लोड करने में इतना समय लगता है। मेरे पास 3 जी प्रक्रिया के 5000 उदाहरण नहीं हो सकते हैं। – JasonMond

+0

मुझे लगता है कि मैं समझता हूं। इनपुट टेक्स्ट प्राप्त करने के बाद, यह कुछ आउटपुट करता है और फिर बाहर निकलता है? या यह आपके लिए कुछ और दर्ज करने का इंतजार कर रहा है –

+0

यह आउटपुट तब निकलता है। – JasonMond

5

शुरू कर दिया है यह communicate() करने के लिए कॉल है कि आपके उपप्रक्रिया मार रहा है है इंतजार नहीं करेंगे। subprocess documentationcommunicate() विधि के अनुसार होगा:

प्रक्रिया के साथ

सहभागिता: stdin के लिए डेटा भेजें। अंत तक फ़ाइल तक पहुंचने तक, stdout और stderr से डेटा पढ़ें। प्रक्रिया समाप्त होने की प्रतीक्षा करें।

आप क्या करना चाहते क्या POpen वस्तु की stdin और stdout सीधे गुण उपप्रक्रिया के साथ संवाद करने के साथ सीधे बातचीत है। कारण अन्य ओएस पाइप बफ़र्स के किसी भी भरने के लिए उपयोग संवाद() के बजाय .stdin.write, .stdout.read से या गतिरोध से बचने के लिए .stderr.read:

चेतावनी: हालांकि, प्रलेखन इस कहावत के खिलाफ सलाह देता है बच्चे की प्रक्रिया को ऊपर और अवरुद्ध करना।

तो आप या तो संभावित गतिरोध के लिए अपने स्वयं के समाधान को लागू करने की जरूरत है, या उम्मीद है कि किसी को आप के लिए एक asynchronous subprocess module लिखा है।

संपादित करें: यहाँ कैसे अतुल्यकालिक उपप्रक्रिया मॉड्यूल इस्तेमाल किया जा सकता का एक quick'n'dirty उदाहरण है:

import asyncsubprocess 

textcollection = ['to', 'be', 'or', 'not', 'to be', 'that is the', 'question'] 

myprocess = asyncsubprocess.Popen(["cat"], 
    stdin = asyncsubprocess.PIPE, 
    stdout = asyncsubprocess.PIPE, 
    stderr = None) 

for text in textcollection: 
    bytes_sent, myoutput, err = myprocess.listen(text) 
    print text, bytes_sent, myoutput, err 

जब मैं इस चलाने के लिए, यह प्रिंट:

to 2 to 
be 2 be 
or 2 or 
not 3 not 
to be 5 to be 
that is the 11 that is the 
question 8 question 
-2
if os.name == 'nt': 
startupinfo = subprocess.STARTUPINFO() 
startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW 
subprocess.call(os.popen(tempFileName), shell=True) 
os.remove(tempFileName) 
संबंधित मुद्दे