रनिंग प्रोग्राम में फोर्स आउटपुट बफर फ्लश


20

मेरे पास एक लंबी चलने वाली अजगर स्क्रिप्ट है जो समय-समय पर मानक आउटपुट के लिए डेटा का उत्पादन करती है जिसे मैंने कुछ इस तरह से किया है:

python script.py > output.txt

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

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

जवाबों:


18

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

एक नज़र डालें जो /proc/$(pidof python)/fdमान्य फ़ाइल वर्णनकर्ता को देखने के लिए। $(pidof x)' x' नाम की प्रक्रिया का PID लौटाता है ।

# your python script is running merrily over there.... with some PID you've determined.
#
# load gdb
gdb
#
# attach to python interpreter (use the number returned by $(pidof python))
attach 1234
#
# force a sync within the program's world (1 = stdout, which is redirected in your example)
call fsync(1)
#
# the call SHOULD have returned 0x0, sync successful.   If you get 0xffffffff (-1), perhaps that wasn't stdout.  0=stdin, 1=stdout, 2=stderr
#
# remove our claws from poor python
detach
#
# we're done!
quit

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

(gdb कमान ' info functions' कार्यों उपलब्ध सभी सूची जाएगा। सावधान हालांकि। आप ऑपरेटिंग रहे LIVE एक प्रक्रिया पर।)

वहाँ भी कमांड है peekfd( psmiscडेबियन जेसी और अन्य पर पैकेज में पाया गया ) जो आपको यह देखने की अनुमति देगा कि प्रक्रिया के बफ़र्स में क्या छुपा है। फिर से, /proc/$(pidof python)/fdआप पीएफ के तर्क के रूप में देने के लिए आपको मान्य फ़ाइल डिस्क्रिप्टर दिखाएंगे।

यदि आपको -uअजगर के बारे में याद नहीं है , तो आप हमेशा stdbuf(/ coreutils, पहले से स्थापित) के साथ एक कमांड को उपसर्ग कर सकते हैं , जिसे स्टड / stdout / stderr को असंबद्ध, लाइन बफर या वांछित के रूप में बफ़र करने के लिए सेट करें:

stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output

बेशक, man pagesआपके दोस्त हैं, हे! शायद एक उपनाम भी यहाँ उपयोगी हो सकता है।

alias python='python -u'

अब आपका अजगर हमेशा -uआपके सभी कमांड लाइन प्रयासों के लिए उपयोग करता है !


5

पहले सुनिश्चित करें कि आपके पास पायथन (या कम से कम ग्लिबक) के लिए डिबगिंग प्रतीक हैं। पर फेडोरा 1 आप उनके साथ स्थापित कर सकते हैं:

dnf debuginfo-install python

फिर चल रहे स्क्रिप्ट में gdb संलग्न करें और निम्नलिखित कमांड चलाएं:

[user@host ~]$ pidof python2
9219
[user@host ~]$ gdb python2 9219
GNU gdb (GDB) Fedora 7.7.1-13.fc20
...
0x00007fa934278780 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81  T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) call fflush(stdout)
$1 = 0
(gdb) call setvbuf(stdout, 0, 2, 0)
$2 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 9219] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2, process 9219

यह स्टडआउट को फ्लश करेगा और बफरिंग को भी अक्षम करेगा । 2से setvbufकॉल के महत्व है _IONBFअपने सिस्टम पर। आपको यह पता लगाने की आवश्यकता होगी कि आपकी ( grep _IONBF /usr/include/stdio.hचाल होना चाहिए) क्या है।

मैं क्या के कार्यान्वयन में देखा है के आधार पर PyFile_SetBufSizeऔर PyFile_WriteStringCPython 2.7 में, यह बहुत अच्छी तरह से काम करना चाहिए, लेकिन मैं किसी भी गारंटी नहीं दे सकता।


1 फेडोरा में एक विशेष प्रकार का RPM शामिल है जिसे debuginfo rpms कहा जाता है । ये स्वचालित रूप से बनाए गए RPM में प्रोग्राम फ़ाइलों से डिबगिंग जानकारी होती है, लेकिन बाहरी फ़ाइल में चली जाती है।


मैंने अजगर 2.7 की कोशिश की और उसी परिणाम के साथ समाप्त हुआ। मैं आपके द्वारा पोस्ट किए गए डिबगिंग अपडेट पर एक नज़र डालूंगा।
DarkHeart

क्या यह की कीमत के लिए, CPython 3.5 आई / ओ (का एक अलग कार्यान्वयन के लिए लगता है fileobject.cकी तुलना में) 2.7 । किसी को ioमॉड्यूल में खुदाई करने की आवश्यकता है ।
बजे क्रिस्टियन सियुपिटु

@DarkHeart, आप इस तरह एक साधारण कार्यक्रम के साथ पहले परीक्षण करना चाह सकते हैं ।
क्रिस्टियन सियुपिटु

4

आपकी तात्कालिक समस्या का कोई समाधान नहीं है। यदि आपकी स्क्रिप्ट पहले ही शुरू हो चुकी है, तो आप इस तथ्य के बाद बफरिंग मोड को नहीं बदल सकते। ये सभी इन-मेमोरी बफ़र हैं और यह सब तब सेट होता है जब स्क्रिप्ट शुरू होती है, फ़ाइल हैंडल खोले जाते हैं, पाइप बनाए जाते हैं, आदि।

एक लंबी-शॉट के रूप में, यदि और केवल अगर कुछ या सभी बफरिंग का सवाल आउटपुट पर IO स्तर पर किया जा रहा है, तो आप एक syncकमांड कर सकते हैं ; लेकिन यह आमतौर पर इस तरह के एक मामले में संभावना नहीं है।

भविष्य में आप स्क्रिप्ट चलाने के लिए पायथन के -uविकल्प * का उपयोग कर सकते हैं । सामान्य तौर पर, कई आदेशों में stdin / stdout बफ़रिंग को अक्षम करने के लिए कमांड-विशिष्ट विकल्प होते हैं, और आपको पैकेज unbufferसे कमांड के साथ कुछ सामान्य सफलता भी मिल सकती है expect

A Ctrl+ के Cकारण सिस्टम-लेवल बफ़र्स तब फ्लश हो जाएगा जब प्रोग्राम बाधित हो जाता है जब तक कि बफ़रिंग पाइथन द्वारा स्वयं नहीं की जाती है और इसने अपने स्वयं के बफ़र्स को Ctrl+ के साथ फ़्लश करने के लिए तर्क को लागू नहीं किया है C। एक निलंबित, दुर्घटना, या हत्या इतनी दयालु नहीं होगी।

* बल स्टड, stdout और stderr पूरी तरह से अप्रभावित हो।


2

पायथन 2.7.7 दस्तावेज़ीकरण, अनुभाग "पायथन सेटअप और उपयोग", उपधारा 1. कमांड लाइन और पर्यावरण , इस पायथन विवरण का वर्णन करता है:

-u

बल स्टड, stdout और stderr पूरी तरह से अप्रभावित हो। उन प्रणालियों पर जहां यह मायने रखता है, बाइनरी मोड में स्टडिन, स्टडआउट और स्टेडर भी डालते हैं।

ध्यान दें कि file.readlines () और फ़ाइल ऑब्जेक्ट्स (sys.stdin में लाइन के लिए) में आंतरिक बफ़रिंग है जो इस विकल्प से प्रभावित नहीं है। इसके चारों ओर काम करने के लिए, आप 1: लूप के अंदर file.readline () का उपयोग करना चाहेंगे।

और यह पर्यावरण चर भी:

PYTHONUNBUFFERED

यदि यह एक गैर-खाली स्ट्रिंग पर सेट है, तो यह -u विकल्प को निर्दिष्ट करने के बराबर है।


1
धन्यवाद - लेकिन ये दोनों ऐसे विकल्प की तरह लग रहे हैं जिन्हें मुझे तब निर्दिष्ट करने की आवश्यकता होगी जब मैंने पहली बार अपनी पायथन स्क्रिप्ट चलाई थी। मैं सोच रहा था कि वहाँ एक स्क्रिप्ट अपने उत्पादन डंप करने के लिए एक चल स्क्रिप्ट पाने के लिए है।
जॉलीबेर

मेरा मानना ​​है कि ऐसा कोई समाधान नहीं है, क्योंकि डेटा शायद एक मेमोरी बफर में कहीं है। आपको अजगर में एक dll इंजेक्षन करने की आवश्यकता होगी जो इसके निष्पादन योग्य को अच्छी तरह से जानता है कि बफर कहां है और इसे कैसे लिखना है। मेरा मानना ​​है कि ज्यादातर लोग उपरोक्त 2 विधियों में से एक का उपयोग करेंगे। सभी के बाद एक पर्यावरण चर जोड़ना आसान है।
१५:१५ को १२:१५ पर harrymc

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

एक दूर-दराज विधि, यदि आप जानते हैं कि डेटा कैसा दिखता है , तो प्रोसेस एक्सप्लोरर का उपयोग करके प्रक्रिया की पूरी मेमोरी डंप लेना है , फिर फ़ाइल में स्ट्रिंग्स की खोज करें। यह प्रक्रिया को समाप्त नहीं करेगा, इसलिए आप अभी भी अन्य तरीकों की कोशिश कर सकते हैं।
21

मैं linux पर हूँ - क्या उस सॉफ्टवेयर के linux समकक्ष हैं?
जोलीबर

2

ऐसा लगता है कि मैं Ctrl-C चलाने के बाद बफर आउटपुट द्वारा खोने के बारे में अधिक सतर्क था; इस पोस्ट के अनुसार मुझे अपेक्षा करनी चाहिए कि यदि मेरे प्रोग्राम का सामान्य निकास है, तो यदि मैं Ctrl-C मारता हूं तो बफर को फ्लश किया जाएगा। दूसरी ओर, यदि मैं स्क्रिप्ट को SIGKILL या समान के साथ मारता हूं, तो मैं बफ़र्ड आउटपुट खो दूंगा।


आपको यह जानने के लिए प्रयास करना होगा। Ctrl-C निम्न स्तर के IO बफ़र्स को फ़्लश करने का कारण बनेगा। यदि पायथन अपने स्वयं के बफ़रिंग करता है तो Ctrl-C केवल उन्हें फ्लश करेगा यदि ऐसा करने के लिए तर्क को लागू करने के लिए पायथन पर्याप्त है। उम्मीद है कि पायथन ने एक पहिया को सुदृढ़ नहीं करने का फैसला किया और सिस्टम के बफरिंग के सामान्य स्तर पर निर्भर करता है। मुझे कोई अंदाजा नहीं है अगर ऐसा है। लेकिन चेतावनी दी हो।
जेसन सी

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

0

मुझे लगता है कि एक अन्य संभावित समाधान कोर डंप के साथ प्रक्रिया को मारने के लिए मजबूर कर सकता है और फिर मरणोपरांत स्मृति सामग्री का विश्लेषण कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.