2013-03-15 8 views
7

मेरे पास एक मेमोरी गहन पायथन एप्लिकेशन है (कई जीबी से सैकड़ों एमबी के बीच)।
मेरे पास कुछ छोटे छोटे लिनक्स निष्पादन योग्य हैं जिन्हें मुख्य एप्लिकेशन को चलाने की आवश्यकता है, उदा।पायथन फोर्क और मेमोरी आवंटन त्रुटियों को समझना

child = Popen("make html", cwd = r'../../docs', stdout = PIPE, shell = True) 
child.wait() 

जब मैं इन बाह्य उपयोगिताओं चलाने (एक बार, लंबे समय से मुख्य प्रक्रिया रन के अंत में) subprocess.Popen का उपयोग कर मैं कभी कभी OSError: [Errno 12] Cannot allocate memory मिलता है।
मुझे समझ में नहीं आता क्यों ... अनुरोधित प्रक्रिया छोटी है!
सिस्टम में कई और गोले के लिए पर्याप्त स्मृति है।

मैं लिनक्स (उबंटू 12.10, 64 बिट्स) का उपयोग कर रहा हूं, इसलिए मुझे लगता है कि सबप्रोसेस कॉल फोर्क।
और फोर्क मेरी मौजूदा प्रक्रिया को फोर्क करता है, इस प्रकार उपभोग की गई स्मृति की मात्रा को दोगुना कर देता है, और विफल रहता है ??
"लिखने पर प्रतिलिपि" के साथ क्या हुआ?

क्या मैं फोर्क के बिना एक नई प्रक्रिया उत्पन्न कर सकता हूं (या कम से कम स्मृति की प्रतिलिपि के बिना - ताजा शुरू करना)?

संबंधित:

The difference between fork(), vfork(), exec() and clone()

fork() & memory allocation behavior

Python subprocess.Popen erroring with OSError: [Errno 12] Cannot allocate memory after period of time

Python memory allocation error using subprocess.Popen

+1

[क्या आपने इस प्रश्न को संबंधित प्रश्न पर पढ़ा है] (http://stackoverflow.com/a/13329386/4279)? – jfs

+0

मेरे पास है, धन्यवाद। वहां कुछ मूल्यवान कामकाज हैं, जिनमें से कुछ मैं उपयोग कर सकता हूं। मैं एक असली समाधान की उम्मीद कर रहा था - पाइथन के भीतर से एक नई प्रक्रिया को बढ़ाने की क्षमता जो सभी प्रक्रिया मेमोरी को ला फोर्क की प्रतिलिपि नहीं बनाती है। –

उत्तर

3

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

सर्वर::

import rfoo 
import subprocess 

class MyHandler(rfoo.BaseHandler): 
    def RPopen(self, cmd): 
     c = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
     c.wait() 
     return c.stdout.read() 

rfoo.UnixServer(MyHandler).start('rfoosocket') 

ग्राहक

यहाँ एक उदाहरण एक नामित यूनिक्स सॉकेट बुलाया rfoosocket साथ rfoo (http://code.google.com/p/rfoo/) का उपयोग कर (आप स्पष्ट रूप से इस्तेमाल कर सकते हैं अन्य कनेक्शन प्रकार का समर्थन करता rfoo, या किसी अन्य RPC पुस्तकालय) है :

import rfoo 

# Waste a bunch of memory before spawning the child. Swap out the RPC below 
# for a straight popen to show it otherwise fails. Tweak to suit your 
# available system memory. 
mem = [x for x in range(100000000)] 

c = rfoo.UnixConnection().connect('rfoosocket') 

print rfoo.Proxy(c).RPopen('ls -l') 

आप वास्तविक समय आगे पीछे coprocess बातचीत अपने पैदा की subprocesses इस मॉडल शायद के साथ की जरूरत है काम नहीं करेगा, लेकिन आप इसे हैक करने में सक्षम हो सकते हैं। आप संभावित रूप से उपलब्ध तर्कों को साफ़ करना चाहते हैं जिन्हें आपकी विशिष्ट आवश्यकताओं के आधार पर पॉपन को पारित किया जा सकता है, लेकिन यह सब अपेक्षाकृत सरल होना चाहिए।

आपको क्लाइंट की शुरुआत में सर्वर लॉन्च करने और सॉकेट फ़ाइल (या बंदरगाह) को निकालने के लिए साफ़ करने के लिए इसे सरल बनाना चाहिए।

+0

'रोपेन' एक डेडलॉक का कारण बनता है यदि 'cmd' अपने stdout ओएस पाइप बफर को भरने के लिए पर्याप्त आउटपुट उत्पन्न करता है। – jfs

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