2011-10-10 14 views
24

एनबी। मैंने Log output of multiprocessing.Process देखा है - दुर्भाग्यवश, यह इस प्रश्न का उत्तर नहीं देता है।पायथन मल्टीप्रोसेसिंग: मैं बाल प्रक्रिया से विश्वसनीय रूप से स्टडआउट कैसे रीडायरेक्ट कर सकता हूं?

मैं मल्टीप्रोसेसिंग के माध्यम से एक बाल प्रक्रिया (विंडोज़ पर) बना रहा हूं। मैं कंसोल पर दिखाई देने के बजाय, बाल प्रक्रिया के stdout और stderr आउटपुट के सभी को लॉग फ़ाइल पर रीडायरेक्ट करने के लिए चाहता हूं। एकमात्र सुझाव मैंने देखा है कि बच्चे की प्रक्रिया के लिए sys.stdout को फ़ाइल में सेट करना है। हालांकि, यह विंडोज़ पर stdout पुनर्निर्देशन के व्यवहार के कारण, सभी stdout आउटपुट को प्रभावी ढंग से पुनर्निर्देशित नहीं करता है।

समस्या को वर्णन करने के लिए निम्न कोड

#include <iostream> 

extern "C" 
{ 
    __declspec(dllexport) void writeToStdOut() 
    { 
     std::cout << "Writing to STDOUT from test DLL" << std::endl; 
    } 
} 

तो बना सकते हैं और निम्नलिखित है, जो इस DLL का आयात करता है और फ़ंक्शन को कॉल की तरह एक अजगर स्क्रिप्ट चलाने के साथ Windows DLL का निर्माण:

from ctypes import * 
import sys 

print 
print "Writing to STDOUT from python, before redirect" 
print 
sys.stdout = open("stdout_redirect_log.txt", "w") 
print "Writing to STDOUT from python, after redirect" 

testdll = CDLL("Release/stdout_test.dll") 
testdll.writeToStdOut() 

मेरे जैसा ही व्यवहार देखने के लिए, संभवतः डीएलएल को एक पायथन उपयोग के मुकाबले एक अलग सी रनटाइम के खिलाफ बनाया जाना आवश्यक है। मेरे मामले में, अजगर विजुअल स्टूडियो 2010 के साथ बनाया गया है, लेकिन मेरे DLL वी.एस. के साथ बनाया गया है 2005

व्यवहार मुझे लगता है कि कंसोल से पता चलता है: फ़ाइल stdout_redirect_log.txt समाप्त होता है

> stdout_test.py 

Writing to STDOUT from python, before redirect 

Writing to STDOUT from test DLL 

जबकि युक्त

Writing to STDOUT from python, after redirect 

दूसरे शब्दों में, sys.stdout की स्थापना DLL द्वारा उत्पन्न stdout उत्पादन रीडायरेक्ट करने में विफल। यह विंडोज में stdout पुनर्निर्देशन के लिए अंतर्निहित एपीआई की प्रकृति को देखते हुए unsurprising है। मुझे इस समस्या का सामना मूल/सी ++ स्तर पर हुआ है और किसी प्रक्रिया के भीतर से stdout को विश्वसनीय रूप से रीडायरेक्ट करने का कोई तरीका नहीं मिला है। इसे बाहरी रूप से किया जाना है।

यह वास्तव में बहुत कारण मैं एक बच्चे की प्रक्रिया शुरू करने रहा है - यह तो है कि मैं अपने पाइप को बाहर से कनेक्ट करने और इस प्रकार की गारंटी है कि मैं इसके उत्पादन के सभी अवरोध उत्पन्न कर रहा हूँ कर सकते हैं। मैं निश्चित रूप से pywin32 साथ मैन्युअल प्रक्रिया शुरू करके ऐसा कर सकते हैं, लेकिन मैं बहुत ज्यादा आदेश प्रगति प्राप्त करने के लिए, एक बहु पाइप वस्तु के माध्यम से बच्चे की प्रक्रिया के साथ संवाद करने की क्षमता विशेष रूप से, बहु की सुविधाओं का उपयोग करने में सक्षम होना चाहते हैं अद्यतन। सवाल अपने आईपीसी सुविधाओं और के लिए बहु मज़बूती से एक फाइल करने के लिए बच्चे की stdout और stderr उत्पादन के सभी पुनर्निर्देशित करने के लिए दोनों का उपयोग करने के लिए किसी भी तरह से है कि क्या वहाँ है।

अद्यतन: multiprocessing.Processs के लिए स्रोत कोड को देखते हुए, तो वह एक स्थिर सदस्य, _Popen, जो लगता है कि यह प्रक्रिया बनाने के लिए इस्तेमाल वर्ग ओवरराइड करने के लिए इस्तेमाल किया जा सकता है। यह कोई नहीं (डिफ़ॉल्ट) के लिए सेट है, तो यह एक multiprocessing.forking._Popen का उपयोग करता है, लेकिन यह कह

multiprocessing.Process._Popen = MyPopenClass 

मैं इस प्रक्रिया निर्माण रद्द कर सकते थे द्वारा तरह दिखता है। हालांकि, हालांकि मैं multiprocessing.forking._Popen से निकाले जाते हैं सकता है, यह है कि मैं अपने कार्यान्वयन, जो परतदार और बहुत नहीं भविष्य प्रूफ लगता में आंतरिक सामान का एक समूह कॉपी करने के लिए होता लग रहा है। अगर यह एकमात्र विकल्प है, तो मुझे लगता है कि मैं शायद पूरी चीज को मैन्युअल रूप से pywin32 के साथ करने के लिए मोटा होगा।

+0

आप उपप्रक्रिया लांच करने के लिए Win32 एपीआई का उपयोग कर सकते हैं, या यह मौजूदा पायथन पुस्तकालयों का उपयोग किया जा करने के लिए है? –

+0

हां, मैंने इस सवाल में उल्लेख किया है कि "मैं निश्चित रूप से pywin32 के साथ प्रक्रिया को लॉन्च करके यह कर सकता हूं"। stdin/stdout बच्चे के लिए संभालती है निर्दिष्ट करने की क्षमता - यह सिर्फ उच्च स्तर, मंच स्वतंत्र बहु ​​क्योंकि जो लापता कार्यशीलता का एक तुच्छ सा की तरह लगता है के मॉड्यूल का परित्याग करने के लिए एक शर्म की बात है लग रहा था। – Tom

+1

दृष्टिकोण मैं ले रहा हूँ (जब तक किसी को एक बेहतर विकल्प के साथ आता है) stdin/stdout एक फ़ाइल पर पुनः निर्देशित साथ उपप्रक्रिया मॉड्यूल के माध्यम से प्रक्रिया शुरू करने के लिए,, और प्रगति संचार के लिए पाइप नाम के एक देशी Windows का उपयोग है। – Tom

उत्तर

7

समाधान का सुझाव एक अच्छा एक है: मैन्युअल रूप से इस तरह के हैं कि आप उनकी stdout/stderr फ़ाइल हैंडल करने के लिए स्पष्ट उपयोग कर सकते है अपनी प्रक्रियाओं पैदा करते हैं। तुम तो सब-प्रक्रिया के साथ संवाद और सॉकेट से अधिक multiprocessing.connection उपयोग करने के लिए एक सॉकेट बना सकते हैं (multiprocessing.Pipe कनेक्शन वस्तु के एक ही प्रकार बनाता है, इसलिए यह आप सभी एक ही भारतीय दंड संहिता की कार्यक्षमता देना चाहिए)।

यहाँ एक दो फ़ाइल उदाहरण है।

master.py:

import multiprocessing.connection 
import subprocess 
import socket 
import sys, os 

## Listen for connection from remote process (and find free port number) 
port = 10000 
while True: 
    try: 
     l = multiprocessing.connection.Listener(('localhost', int(port)), authkey="secret") 
     break 
    except socket.error as ex: 
     if ex.errno != 98: 
      raise 
     port += 1 ## if errno==98, then port is not available. 

proc = subprocess.Popen((sys.executable, "subproc.py", str(port)), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

## open connection for remote process 
conn = l.accept() 
conn.send([1, "asd", None]) 
print(proc.stdout.readline()) 

subproc.py:

import multiprocessing.connection 
import subprocess 
import sys, os, time 

port = int(sys.argv[1]) 
conn = multiprocessing.connection.Client(('localhost', port), authkey="secret") 

while True: 
    try: 
     obj = conn.recv() 
     print("received: %s\n" % str(obj)) 
     sys.stdout.flush() 
    except EOFError: ## connection closed 
     break 

तुम भी गैर अवरुद्ध पाने के लिए this question के लिए सबसे पहले जवाब देखने के लिए चाहते हो सकता है उपप्रक्रिया से पढ़ता ।

1

मुझे नहीं लगता कि आपके पास अपनी टिप्पणी में उल्लिखित फ़ाइल में उपप्रोसेस को रीडायरेक्ट करने से बेहतर विकल्प है।

तरह से सांत्वना खिड़कियों में stdin/बाहर/अं काम प्रत्येक प्रक्रिया है जब यह पैदा हुआ है इसकी std handles परिभाषित किया गया है। आप उन्हें SetStdHandle से बदल सकते हैं। आप अजगर की जब संशोधित sys.stdout आप केवल जहां अजगर प्रिंट बाहर सामान को संशोधित, न कि जहां अन्य DLL के सामान प्रिंट कर रहे हैं। अपने डीएलएल में सीआरटी का हिस्सा यह पता लगाने के लिए GetStdHandle का उपयोग कर रहा है कि कहां प्रिंट करना है। यदि आप चाहते हैं, तो आप अपने डीएलएल में विंडोज एपीआई में या पाइविन 32 के साथ अपनी पायथन लिपि में जो भी पाइपिंग चाहते हैं वह कर सकते हैं। हालांकि मुझे लगता है कि यह subprocess के साथ आसान होगा।

0

मुझे लगता है मैं आधार और कुछ कमी दूर हूँ, लेकिन क्या इसे यहाँ लायक है क्या दिमाग में आया है के लिए जब मैं अपने प्रश्न पढ़ें।

आप stdout और stderr (मैं अपने प्रश्न से कि छाप मिल गया) के सभी को रोक सकता है, तो क्यों जोड़ते हैं या अपनी प्रक्रियाओं में से प्रत्येक के आसपास है कि कब्जा कार्यक्षमता रैप नहीं? फिर एक उपभोक्ता को कतार के माध्यम से कैप्चर किया जाता है जो आप सभी आउटपुट के साथ जो भी कर सकते हैं कर सकते हैं?

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

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