2011-03-23 18 views
10

पढ़ें मुझे एक प्रोग्राम चलाने और stdout पर अपना आउटपुट इकट्ठा करने की आवश्यकता है। इस कार्यक्रम (समाज) को अजगर लिपि की अवधि के लिए पृष्ठभूमि में चलाने की जरूरत है। सोकाट एक बार चलने के बाद डेमॉन मोड में बैठता है, लेकिन पहले यह कुछ लाइनों को आउटपुट करता है कि मुझे अपनी बाकी स्क्रिप्ट की आवश्यकता है।पायथन एक डेमॉन उप-प्रक्रिया चलाएं और stdout

कमान: socat -d -d PTY: PTY:

आउटपुट:

2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/1 
2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/2 
2011/03/23 21:12:35 socat[7476] N starting data transfer loop with FDs [3,3] and [5,5] 

...

मैं मूल रूप से है कि चलाने मेरा कार्यक्रम के शुरू में है और यह स्क्रिप्ट समाप्ति तक चल छोड़ना चाहते हैं, लेकिन मैं जरूरत पाइथन में दो/dev/pts/X नाम पढ़ने के लिए।

क्या कोई मुझे बता सकता है कि यह कैसे करें?

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

#!/usr/bin/python 
from subprocess import Popen, PIPE, STDOUT 

cmd = 'socat -d -d PTY: PTY: &' 

p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 
output = p.stdout.read() 

# Process the output 
print(output) 

किसी भी मदद

संपादित करने के लिए धन्यवाद: लगता है यह stderr करने के लिए लिख सकते हैं, लेकिन स्क्रिप्ट अभी भी बस के साथ और & भी stderr से पढ़ने के बिना hanges।

+1

क्या यह '&' के बिना काम करता है? –

+0

नहीं :(दुख की बात नहीं, यह बस लटकती है। – Jason

+0

क्या आपने यह सत्यापित करने के लिए प्रिंट स्टेटमेंट में जोड़ने का प्रयास किया है कि यह आपके कॉल के बाद 'पॉपन' पर अवरुद्ध है और 'read()' कॉल पर अवरुद्ध नहीं है? – Jeff

उत्तर

18
#!/usr/bin/python 
from subprocess import Popen, PIPE, STDOUT 
import pty 
import os 

cmd = 'socat -d -d PTY: PTY:' 

master, slave = pty.openpty() 

p = Popen(cmd, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True) 
stdout = os.fdopen(master) 
print stdout.readline() 
print stdout.readline() 

आपके संस्करण के साथ दो समस्याएं हैं। सबसे पहले, आप तर्क के बिना पढ़ते हैं जिसका अर्थ है कि यह सब कुछ पढ़ने का प्रयास करेगा। लेकिन चूंकि समाज समाप्त नहीं होता है, यह कभी तय नहीं करता है कि उसने सब कुछ पढ़ा है। रीडलाइन का उपयोग करके, पायथन केवल तब तक पढ़ता है जब तक कि यह एक नई लाइन न पाएं। आपकी समस्या की मेरी समझ से जो आपको चाहिए।

दूसरी समस्या यह है कि सी मानक लाइब्रेरी पाइप पर आउटपुट बफर करेगा। हम हल करते हैं कि ओपनप्टी() फ़ंक्शन के साथ एक पीटीआई बनाकर और इसे सबप्रोसेस के stdout और stderr दोनों में गुजरना। हम उस फ़ाइल डिस्क्रिप्टर को नियमित पायथन ऑब्जेक्ट में बनाने के लिए fdopen का उपयोग करते हैं और हम बफरिंग से छुटकारा पा सकते हैं।

मुझे नहीं पता कि आप फुटबॉल के साथ क्या कर रहे हैं, लेकिन मुझे आश्चर्य है कि यह पीटीआई मॉड्यूल का उपयोग कर बदल सकता है या नहीं। आप एक पीटीआई को दूसरे में कॉपी कर रहे हैं, और ओपनप्टी ptys की एक जोड़ी बना रही है। शायद आप सीधे उन का उपयोग कर सकते हैं?

+0

बहुत बहुत धन्यवाद, यह पूरी तरह से काम करता है। मैं इनबिल्ट पीटीआई मॉड्यूल के साथ सोसाट को बदलना चाहता हूं। – Jason

0

यदि आप इसे स्टडआउट और स्टडर के लिए पाइप के साथ आपूर्ति करते हैं, तो मुझे लगता है कि उपप्रोसेस पाइप को पढ़ने के लिए इंतजार कर देगा। .read() को लगता है कि ईओएफ को पढ़ना चाहिए। उनके बीच, उन दो मुद्दों के प्रकोप एक डेडलॉक बनाता है।

हालांकि, मुझे लगता है कि चूंकि .read() ईओएफ तक पढ़ेगा, यह कोई स्टडर पाइप होने पर भी अवरुद्ध होगा।

मुझे लगता है कि आप थ्रेड में पढ़ना चाहते हैं, मुझे लगता है।

1

उपप्रोसेसर शायद कभी भी स्टडआउट को बंद नहीं करता है, इसलिए read() कॉल हमेशा के लिए प्रतीक्षा करता है। मामलों को और भी खराब बनाने के लिए, यह संभवतः अपने आउटपुट को बफर करेगा जब यह पता चलता है कि यह कंसोल की बजाय एक पाइप है (मानक सी लाइब्रेरी स्वचालित रूप से यह करती है, इसलिए यह ऐप कितनी चतुराई से लिखा गया है इसका एक कार्य नहीं है)। यदि ऐसा है, तो शायद एकमात्र विकल्प एक उम्मीद-शैली लाइब्रेरी का उपयोग करना है जैसे कि Pexpect

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