एक प्रोग्राम के stdout के 10% खोने पाइथन subprocess

मेरे पास एक ऐसा प्रोग्राम है जिसे पायथन के साथ उपप्रोसेसर कहा जाता है। कार्यक्रम जावा में लिखा गया है। हाँ मुझे पता है...

वैसे भी, मुझे कहा गया कार्यक्रम से सभी आउटपुट कैप्चर करने की जरूरत है।

दुर्भाग्यवश, जब मैं subprocess.popen2 या subprocess को कॉल करता हूं। संवाद के साथ खोलें [0], जब मैं subprocess का उपयोग कर रहा हूं, तो मैं आउटपुट डेटा का लगभग 10% खो रहा हूं। Stipout को निर्दिष्ट PIPE और जब मैं फ़ाइल डिस्क्रिप्टर का उपयोग कर रहा हूं (एक खुले से वापसी) stdout को सौंपा गया।

Subprocess में प्रलेखन बहुत स्पष्ट है कि subprocess.PIPE का उपयोग अस्थिर है यदि आप किसी बच्चे की प्रक्रिया से सभी आउटपुट कैप्चर करने का प्रयास कर रहे हैं।

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

डिस्क लिखने से बचने के लिए मैं सभी डेटा मेमोरी में रखना चाहता हूं।

किसी भी सिफारिश का स्वागत है! धन्यवाद!

import subprocess

cmd = 'java -Xmx2048m -cp "/home/usr/javalibs/class:/home/usr/javalibs/libs/dependency.jar" --data data --input input" 

# doesn't get all the data
#
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

OR
# doesn't get all the data
#
fd = open("outputfile",'w')
p = subprocess.Popen(cmd, stdout=fd, shell=True)
p.communicate()
fd.close() # tried to use fd.flush() too.

# also tried
# p.wait() instead of p.communicate(), but wait doesn't really wait for the java program to finish running - it doesn't block

OR
# also fails to get all the data
#
import popen2
(rstdout, rstdin) = popen2.popen2(cmd)

अपेक्षित आउटपुट असीसी लाइनों की एक श्रृंखला है (कुछ हज़ार)। रेखाओं में एक संख्या और रेखा चरित्र का अंत होता है

0\n
1\n
4\n
0\n
...
2
जोड़ा संपादित
विचारों: 2
क्या हमारे पास कुछ पायथन कोड हो सकता है?
जोड़ा लेखक Bittrance, स्रोत
हे, बस stdout कब्जा करने की कोशिश कर रहा है (stderr नहीं)। आउटपुट एक संख्या और रेखा चरित्र का अंत है - यह सभी एसीआईआई आउटपुट की उम्मीद कर रहा है
जोड़ा लेखक ct_, स्रोत
@ jadkik94 और पुल तो दोस्तों मैं आपके समय की सराहना करता हूं लेकिन आप वास्तव में मदद नहीं कर रहे हैं। मैंने पहले से ही कहा है कि उप-प्रोसेस को कॉल करते समय पीआईपीई में समस्याएं हैं (मैंने कई बार दस्तावेज पढ़ा है) तो आप इसे सही तरीके से कैसे करते हैं?
जोड़ा लेखक ct_, स्रोत
@ पाउल यह सभी आउटपुट नहीं पढ़ रहा है। मैं नए लाइन अक्षरों के साथ ~ 1300 + संख्याओं की लाइनों की उम्मीद कर रहा हूं - इनपुट के आधार पर। और हाँ इंतजार वास्तव में "प्रतीक्षा" नहीं करता है मेरी पाइथन लिपि पिछले निष्पादन जारी रखती है जहां मैंने उपप्रोसेसर को फोर्क किया था। सटीकता के लिए, मैं जिस समस्या का सामना कर रहा हूं उसे समझा रहा हूं।
जोड़ा लेखक ct_, स्रोत
@ पाउल जो मैं प्रतिक्रिया के रूप में नहीं देख रहा हूं। अगर यह अस्थिर है, तो मैं इसे सही तरीके से कैसे करना है इसके बारे में पढ़ सकता हूं। और जब मैं एफडी का उपयोग करता हूं तो मुझे अभी भी सभी डेटा नहीं मिल रहा है - मुझे संदेह है कि stdout में fd असाइन करने के लिए समान समस्याएं हैं जैसे subprocess.PIPE को stdout को असाइन करना।
जोड़ा लेखक ct_, स्रोत
आउटपुट का अंतिम 10%। स्पष्ट करने के लिए प्रश्न के लिए एक अद्यतन पोस्ट किया। धन्यवाद!
जोड़ा लेखक ct_, स्रोत
आप "10%" क्या गायब हैं? क्या यह शुरुआत में है, अंत? आप किस आउटपुट की उम्मीद कर रहे थे?
जोड़ा लेखक Joel Cornett, स्रोत
"लेकिन इंतजार वास्तव में जावा प्रोग्राम को चलाने के लिए इंतजार नहीं करता है - यह ब्लॉक नहीं करता है" <- पूरी तरह से गलत भी। क्या आप सुनिश्चित हैं कि आपका सबप्रोसेस जिस तरह से आप उम्मीद कर रहे हैं उस पर काम कर रहा है?
जोड़ा लेखक the paul, स्रोत
आपको क्या त्रुटियां मिल रही हैं?
जोड़ा लेखक the paul, स्रोत
दाएं, subprocess.PIPE को इनपुट और आउटपुट एफडीएस को एक-दूसरे को अवरुद्ध करने से रोकने के लिए, संचार() या अन्यथा सावधानी के साथ उपयोग किया जाना चाहिए। यह आंशिक रूप से मेरा मतलब है "ठीक से इस्तेमाल किया"।
जोड़ा लेखक the paul, स्रोत
"सबप्रोसेस में प्रलेखन बहुत स्पष्ट है कि सबप्रोसेस का उपयोग करना। पीआईपीई अस्थिर है यदि आप बच्चे की प्रक्रिया से सभी आउटपुट कैप्चर करने का प्रयास कर रहे हैं।" <- अगर दस्तावेज यह कहता है, तो यह पूरी तरह से गलत है। पीआईपीई पूरी तरह से सुरक्षित है और यदि सही ढंग से उपयोग किया जाता है तो कनेक्टेड एफडी पर सभी आउटपुट प्राप्त होंगे।
जोड़ा लेखक the paul, स्रोत
क्या आप सुनिश्चित हैं कि आपका जावा सबप्रोसेस खुद को फोर्किंग नहीं कर रहा है? यह समझा सकता है कि आपका प्रतीक्षा() कॉल क्यों अवरुद्ध नहीं होता है।
जोड़ा लेखक the paul, स्रोत
मैं आपको आश्वासन देता हूं, यदि आप संवाद का उपयोग करते हैं तो पीआईपीई में "समस्याएं" नहीं होती हैं और आपका डेटा स्मृति में फिट बैठता है (यदि ऐसा नहीं होता है, तो आप अधिक स्पष्ट विफलता देखेंगे)। दस्तावेज़ों में नोट्स लोगों को अनुचित तरीके से इसका उपयोग करने की कोशिश करने से रोकते हैं। मैं करूंगा मदद करना चाहता हूं, लेकिन ऐसा लगता है कि आप वास्तव में सिस्टम के गलत हिस्से को दोष देना चाहते हैं।
जोड़ा लेखक the paul, स्रोत
अधिक विशिष्ट होने के लिए, subprocess.PIPE का उपयोग करके या उपप्रोसेस के आउटपुट में एक एफडी असाइन करना अनिवार्य रूप से सटीक वही बात है जो आपके खोल तब करता है जब आप फ़ाइल में आउटपुट रीडायरेक्शन करते हैं (ओएस का dup2 ( ) </कोड> सिस्टम कॉल)। आप सुरक्षित रूप से यह मान सकते हैं कि भाग काम कर रहा है। आप वहां अपने आदेश के अंत में "` | tee outputcopy "जोड़ने का प्रयास कर सकते हैं; तो आप यह जांच सकते हैं कि outputcopy` की सभी लाइनें आपकी अपेक्षा करती हैं। यदि ऐसा नहीं होता है, तो शायद आपका जावा प्रोग्राम बिल्कुल सही काम नहीं कर रहा है।
जोड़ा लेखक the paul, स्रोत
@ jadkik94 जो यहां एक समस्या होने की संभावना नहीं है; पाइथन या जावा चलाने में सक्षम किसी भी कल्पनीय मशीन पर, कुछ पात्रों की "कुछ हज़ार" रेखाएं आसानी से स्मृति में फिट होंगी।
जोड़ा लेखक the paul, स्रोत
क्या यह संभव है कि कुछ आउटपुट stderr पर लिखा जा रहा है?
जोड़ा लेखक Jeremiah, स्रोत
"नोट इस फ़ंक्शन के साथ stdout = PIPE या stderr = PIPE का उपयोग न करें। चूंकि वर्तमान प्रक्रिया में पाइप को नहीं पढ़ा जा रहा है, इसलिए यदि यह ओएस पाइप बफर भरने के लिए पाइप में पर्याप्त आउटपुट उत्पन्न करता है तो बच्चे की प्रक्रिया अवरुद्ध हो सकती है।" subprocess दस्तावेज़ से
जोड़ा लेखक jadkik94, स्रोत
बड़े डेटा के बारे में संवाद में एक चेतावनी है, लेकिन यह अभी भी एक विकल्प के लिए बहुत अस्पष्ट है ...
जोड़ा लेखक jadkik94, स्रोत
देखें कि क्या यह भी मदद कर सकता है: एक और SO प्रश्न
जोड़ा लेखक jadkik94, स्रोत

2 उत्तर

यह उस प्रक्रिया से संबंधित होना चाहिए जो आप वास्तव में बुला रहे हैं। आप इसे अन्य पायथन स्क्रिप्ट के साथ एक सरल परीक्षण करके सत्यापित कर सकते हैं जो लाइनों को echos बाहर करता है:

out.py

import sys

for i in xrange(5000):
    print "%d\n" % i

sys.exit(0)

test.py

import subprocess

cmd = "python out.py"
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

print output

तो आप यह सत्यापित कर सकते हैं कि यह उस डेटा का आकार नहीं है जो समस्या है, बल्कि उस प्रक्रिया के साथ संचार जिसे आप बुला रहे हैं।

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

यदि उपप्रोसेसर कॉल अनिश्चित काल तक लटक रहा था तो यह एक बफर मुद्दा होगा। लेकिन अगर प्रक्रिया पूरी हो रही है, तो बस लाइनों की कमी है, तो पॉपन अपना काम कर रहा है।

2
जोड़ा
मैं इसे थोड़ा सा स्पिन दूंगा, और परिणाम पोस्ट करूंगा, धन्यवाद!
जोड़ा लेखक ct_, स्रोत

मैंने subdocess का उपयोग stdout पर बहुत बड़े आउटपुट के साथ किया था लेकिन ऐसी समस्या नहीं देखी है। यह निष्कर्ष निकालना मुश्किल है कि आपने जो दिखाया है उससे मूल कारण क्या है। मैं निम्नलिखित जांचूँगा:

चूंकि p.wait() आपके लिए काम नहीं करता है। यह मामला हो सकता है कि जब आप अपना PIPE पढ़ते हैं तो आपका जावा प्रोग्राम अभी भी पिछले 10% प्रिंटिंग में व्यस्त है। p.wait() सीधे पहले प्राप्त करें:

  • PIPE पढ़ने से पहले, एक बड़ा पर्याप्त प्रतीक्षा (30 सेकंड कहें) डालें, क्या आपका 10% दिखाता है?
  • यह संदिग्ध है कि p.wait() आपके जावा प्रोग्राम पर अवरुद्ध नहीं होता है। क्या आपका जावा प्रोग्राम अन्य प्रोग्राम को आगे बढ़ा रहा है?
  • p.wait() के वापसी मूल्य की जांच करें। क्या आपका जावा प्रोग्राम सामान्य रूप से समाप्त हो गया था?

यदि समस्या आपके समवर्ती मॉडल में नहीं है, तो जांचें कि क्या आप अपने जावा कार्यक्रम में सही तरीके से प्रिंट कर रहे हैं:

  • stdout पर प्रिंट करने के लिए आपने अपने जावा प्रोग्राम में किस फ़ंक्शन का उपयोग किया था? क्या यह IOException ?
  • को प्रवण या अनदेखा करता है
  • क्या आपने स्ट्रीम को सही ढंग से फ़्लश किया था? आपका जावा प्रोग्राम समाप्त होने पर अंतिम 10% आपके बफर में उचित फ़्लशिंग के बिना हो सकता है।
2
जोड़ा
आपके साथ वापस आ जाएगा - थोड़ी देर में जेडीआई नोट्स पर काम करने जा रहा है। धन्यवाद!
जोड़ा लेखक ct_, स्रोत