2012-12-17 15 views
5

मैं एक शोध उपकरण लिख रहा हूं और मैंने हाल ही में पाइथन में निर्मित लॉगर कार्यक्षमता का उपयोग करने के लिए "प्रिंट" कथन का उपयोग करने से स्विच किया है। यह, मैंने तर्क दिया, मुझे उपयोगकर्ता को स्क्रीन पर डंप करने के अलावा आउटपुट को फ़ाइल में डंप करने का विकल्प देने की अनुमति होगी।बाहरी एप्लिकेशन से लॉग इन

अभी तक इतना अच्छा है। पाइथन में मेरे कोड का हिस्सा स्क्रीन और फ़ाइल दोनों को डंप करने के लिए "logger.info" और "logger.error" का उपयोग करता है। "लॉगर" मॉड्यूल-चौड़ा लॉगर है। यह हिस्सा एक आकर्षण की तरह काम करता है।

हालांकि, कई बिंदुओं पर, मैं खोल के माध्यम से निष्पादन योग्य चलाने के लिए "subprocess.call" का उपयोग करता हूं। तो, कोड भर में, मैं की तरह

proc = subprocess.call(command) 

लाइनों इस आदेश से आउटपुट स्क्रीन पर प्रिंट, हमेशा की तरह होता है, लेकिन यह है कि उपयोगकर्ता निर्दिष्ट फ़ाइल को डंप नहीं होगा।

एक संभावित विकल्प फाइल करने के लिए एक पाइप को खोलने के लिए होगा:

proc = subprocess.call(command, stdout=f, stderr=subprocess.OUTPUT) 

लेकिन वह केवल फाइल करने के लिए स्क्रीन के लिए नहीं डंप और होगा।

असल में, मेरा प्रश्न इस पर उबलता है: क्या कोई तरीका है कि मैं अपने मौजूदा लॉगर का लाभ उठा सकता हूं, विशेष रूप से subprocess.call के लिए फ़ाइलों के लिए एक और हैंडलर बनाने के बिना? (शायद आउटपुट को लॉगर में रीडायरेक्ट करके?) या यह मौजूदा सेटअप के बाद असंभव है? यदि उत्तरार्द्ध, मैं सेटअप कैसे सुधार सकता हूं?

(ओह, भी, यह बहुत अच्छा है, तो लॉगिंग 'वास्तविक समय' में थे हो सकता है, ताकि निष्पादन से संदेश लॉग ऑन हैं के रूप में वे प्राप्त कर रहे हैं।)

किसी भी मदद के लिए धन्यवाद! :)

+1

लेनार्ट रीगेब्रो [स्ट्रीम लॉगर क्लास] (http://stackoverflow.com/a/4838875/190597) आपकी स्थिति में अच्छी तरह से काम करेगा। – unutbu

+0

संदर्भ के लिए धन्यवाद! यह मेरे मामले के लिए बहुत अच्छा काम करता है। –

उत्तर

3

फ़ाइल में stdout पाइप करने के बजाय, आप इसे PIPE पर पाइप कर सकते हैं, और फिर उस पीआईपीई से पढ़ सकते हैं और लॉगर को लिख सकते हैं। कुछ इस तरह:

proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.OUTPUT) 
for line in proc.stdout: 
    logging.info(line) 

हालांकि, वहाँ एक भी सरल जवाब है: आप एक फ़ाइल हैंडल के साथ एक फ़ाइल जैसी वस्तु का उपयोग करने के लिए है, लेकिन आप पाइप के शीर्ष कि logging करने के लिए प्रत्येक पंक्ति से गुजरता है पर बना सकते हैं। आप इस ऑब्जेक्ट को स्वयं लिख सकते हैं, लेकिन, जैसा कि @unutbu कहते हैं, किसी ने इसे पहले से ही this question में किया है। तो:

with StreamLogger(logging.INFO) as out: 
    proc = subprocess.call(command, stdout=out, stderr=subprocess.OUTPUT) 

बेशक आप भी अस्थायी रूप से लपेट कर सकते हैं stdout लकड़हारा करने के लिए लिखने के लिए और बस के माध्यम से उत्पादन गुजरती हैं, उदाहरण के लिए, this confusingly identically-named class का उपयोग कर:

with StreamLogger('stdout'): 
    proc = subprocess.call(command, stderr=subprocess.OUTPUT) 
+0

अंतिम लिंक में कोड के संदर्भ के लिए धन्यवाद। पढ़ने में दिलचस्प था। –

3

unutbu's comment अच्छा है; आपको Lennart's answer पर एक नज़र रखना चाहिए।

tee की कार्यक्षमता की तरह कुछ आपको क्या करना होगा है, लेकिन subprocess मॉड्यूल ओएस हैंडल का स्तर, जिसका अर्थ है कि उपप्रक्रिया द्वारा लिखित डेटा अपने अजगर कोड से नहीं देखा जा सकता पर काम करता है, कुछ फ़ाइल से कहना ऑब्जेक्ट की तरह आप लिखते हैं कि कौन से लॉग और प्रिंट जो भी लिखे गए हैं।

साथ ही साथ लेनार्ट के उत्तर का उपयोग करके, आप इस तरह की चीज को तीसरे पक्ष की लाइब्रेरी का उपयोग करके sarge (प्रकटीकरण: मैं इसका रखरखाव कर सकता हूं) कर सकता हूं। यह लॉगिंग से अधिक के लिए काम करता है।मान लीजिए आप एक प्रोग्राम है जो इस तरह के रूप उत्पादन, उत्पन्न करता है:

# echotest.py 
import time 
for i in range(10): 
    print('Message %d' % (i + 1)) 

और आप अपनी स्क्रिप्ट में यह कब्जा यह लॉग इन करें और स्क्रीन पर प्रिंट करना चाहते हैं:

#subptest.py 
from sarge import capture_stdout 
import logging 
import sys 

logging.basicConfig(filename='subptest.log', filemode='w', 
        level=logging.INFO) 

p = capture_stdout('python echotest.py', async=True) 
while True: 
    line = p.stdout.readline() 
    line = line.strip() 
    # depending on how the child process generates output, 
    # sometimes you won't see anything for a bit. Hence only print and log 
    # if you get something 
    if line: 
     print(line) 
     logging.info(line) 

    # Check to see when we can stop - after the child is done. 
    # The return code will be set to the value of the child's exit code, 
    # so it won't be None any more. 

    rc = p.commands[0].process.poll() 
    # if no more output and subprocess is done, break 
    if not line and rc is not None: 
     break 

आप ऊपर स्क्रिप्ट चलाते हैं , आप कंसोल के लिए बाहर मुद्रित करने के:

$ python subptest.py 
Message 1 
Message 2 
Message 3 
Message 4 
Message 5 
Message 6 
Message 7 
Message 8 
Message 9 
Message 10 

और जब हम लॉग फ़ाइल देखें, हम देखते हैं:

$ cat subptest.log 
INFO:root:Message 1 
INFO:root:Message 2 
INFO:root:Message 3 
INFO:root:Message 4 
INFO:root:Message 5 
INFO:root:Message 6 
INFO:root:Message 7 
INFO:root:Message 8 
INFO:root:Message 9 
INFO:root:Message 10 
+0

टिप के लिए धन्यवाद! :) –