2010-07-06 20 views
16

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

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    return p 

def runTest(path, flags, name): 
    log = open(name, "w") 
    print >> log, "Calling executable A" 
    a_ret = run(path + "executable_a_name" + flags, log) 
    print >> log, "Calling executable B" 
    b_ret = run(path + "executable_b_name" + flags, log) 
    print >> log, "More stuff" 
    log.close() 

लॉग फ़ाइल है: कॉलिंग निष्पादन एक निष्पादन बी कॉलिंग अधिक सामान [... दोनों निष्पादनयोग्य से stdout ...]

वहाँ एक रास्ता मैं करने के लिए एक के stdout फ्लश कर सकते हैं पॉपन को बुलाए जाने के बाद लॉग, उदाहरण के लिए? एक और चीज जो प्रासंगिक हो सकती है: निष्पादन योग्य ए शुरू होता है तो बी पर पेंड करता है, और बी के बाद सामान प्रिंट और खत्म हो जाता है, फिर ए और अधिक सामान प्रिंट करता है और समाप्त होता है।

मैं आरएचई लिनक्स पर पायथन 2.4 का उपयोग कर रहा हूं।

+0

जब मैंने stdout = subprocess.PIPE का उपयोग किया था और बाहरी लूप लॉग फ़ाइल में सबकुछ लिखता था, तो मैं एक्जिक्यूटिव के आउटपुट के साथ अपना टेक्स्ट लिखने में सक्षम था। जब मैं कोई पाठ नहीं जोड़ता, लॉग में इस क्रम में सामग्री होती है: 1) आउटपुट 2) बी आउटपुट 3) ए आउटपुट के बाकी। मैं उन चरणों में से पहले या बाद में पाठ जोड़ सकता था। अब मैं केवल लॉग के प्रारंभ या अंत में टेक्स्ट जोड़ सकता हूं। पॉपन के बाद एक प्रतीक्षा() जोड़ना स्क्रिप्ट को लटकता है क्योंकि बी एक खत्म होने तक शुरू नहीं होता है, जो यह नहीं करेगा, क्योंकि ए बी से हैंडशेकिंग की प्रतीक्षा करता है। क्या इस दृष्टिकोण के साथ लॉग में अपना खुद का टेक्स्ट इंटरल्यू करना संभव है? – jasper77

उत्तर

15

आप यह सुनिश्चित करने के लिए प्रत्येक पॉपन ऑब्जेक्ट पर .wait() को कॉल कर सकते हैं कि यह समाप्त हो गया है और फिर log.flush() को कॉल करें। इस तरह हो सकता है कि कुछ:

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    ret_code = p.wait() 
    logfile.flush() 
    return ret_code 

आप अपने बाहरी समारोह में popen वस्तु के साथ बातचीत करने के लिए आप .Wait को स्थानांतरित कर सकता है की जरूरत है() वहाँ के बजाय कहते हैं।

+1

यदि मैं रन() फ़ंक्शन में प्रतीक्षा() डालता हूं, तो निष्पादन योग्य बी समाप्त होने तक चलना शुरू नहीं होगा, और चूंकि बी बी तक खत्म नहीं होता है, इसलिए स्क्रिप्ट लटका दी जाएगी। हालांकि, मैंने पाया कि यदि मेरे पास runTest() है, बाहरी फ़ंक्शन, ए तो बी चलाएं, फिर ए पर प्रतीक्षा करें और लॉग फ्लश करें, रनटास्ट के अंत में प्रिंट की गई एक पंक्ति वास्तव में लॉग फ़ाइल के अंत में दिखाई देती है। मुझे अभी भी बी चलाने से ठीक पहले फ़ाइल में टेक्स्ट प्रिंट करने का कोई तरीका नहीं मिला है। मुझे नहीं पता कि एक रास्ता है। – jasper77

+2

'logfile.flush()' का बाल प्रक्रियाओं पर कोई प्रभाव नहीं पड़ता है। – jfs

1

आपको जारी रखने से पहले प्रक्रिया समाप्त होने तक प्रतीक्षा करने की आवश्यकता है। मैंने कोड को एक संदर्भ प्रबंधक का उपयोग करने के लिए भी परिवर्तित कर दिया है, जो क्लीनर है।

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    p.wait() 
    return p 

def runTest(path, flags, name): 
    with open(name, "w") as log: 
     print >> log, "Calling executable A" 
     a_ret = run(path + "executable_a_name" + flags, log) 
     print >> log, "Calling executable B" 
     b_ret = run(path + "executable_b_name" + flags, log) 
     print >> log, "More stuff" 
+0

संदर्भ प्रबंधक एक पायथन 2.6 सुविधा है जो कि अभी भी RHEL5 सिस्टम चलाने वाले किसी के लिए उपलब्ध नहीं है। जब तक आरएचईएल 6 बाहर नहीं आ जाता है, तब तक उनका उपयोग नहीं करना सबसे अच्छा होता है। – Jerub

+0

आप किसी भी अन्य आयात से पहले '__future__ आयात with_statement'' का उपयोग करके पायथन 2.5 में संदर्भ प्रबंधकों का उपयोग कर सकते हैं। – detly

+0

लेकिन ऐसा लगता है कि आरएचईएल 5 पाइथन 2.4 पर फंस गया है। –

2

मैं कहता हूं कि इसे वास्तविक सरल रखें। छद्म कोड बुनियादी तर्क:

write your start messages to logA 
execute A with output to logA 
write your in-between messages to logB 
execute B with output to logB 
write your final messages to logB 
when A & B finish, write content of logB to the end of logA 
delete logB 
+0

एक लॉग फ़ाइल के बजाय ए और बी के लिए दो अलग-अलग लॉग फ़ाइलों का उपयोग करने के लिए सोच-बाहर-द-बॉक्स सुझाव के लिए धन्यवाद। मुझे इसके बारे में सोचना होगा। – jasper77

1

मैं यह समझ B के लिए A कार्यक्रम प्रतीक्षा करता है केवल B बाहर निकलता है के बाद अपनी बात और A बाहर निकलता है क्या करने के लिए के रूप में।

तो B चल रहा है तो आप उलटे क्रम में प्रक्रियाओं शुरू कर सकता है A बिना शुरू कर सकते हैं:

from os.path import join as pjoin 
from subprocess import Popen 

def run_async(cmd, logfile): 
    print >>log, "calling", cmd 
    p = Popen(cmd, stdout=logfile) 
    print >>log, "started", cmd 
    return p 

def runTest(path, flags, name): 
    log = open(name, "w", 1) # line-buffered 
    print >>log, 'calling both processes' 
    pb = run_async([pjoin(path, "executable_b_name")] + flags.split(), log) 
    pa = run_async([pjoin(path, "executable_a_name")] + flags.split(), log) 
    print >>log, 'started both processes' 
    pb.wait() 
    print >>log, 'process B ended' 
    pa.wait() 
    print >>log, 'process A ended' 
    log.close() 

नोट: बुला मुख्य प्रक्रियाओं में log.flush() बच्चे प्रक्रियाओं में फ़ाइल बफ़र्स पर कोई प्रभाव नहीं है।

बच्चे प्रक्रियाओं stdout के लिए उपयोग करते हैं ब्लॉक बफरिंग तो आप (यह मानता है कि प्रक्रियाओं का उपयोग लाइन बफरिंग यदि सहभागी चलाने के लिए या वे आई/ओ के लिए सी stdio पुस्तकालय का उपयोग करें) pexpect, pty, or stdbuf का उपयोग कर जल्दी ही फ्लश करने के लिए उन्हें मजबूर करने के लिए कोशिश कर सकते।

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