डॉकटर में डिटैच होने पर पायथन ऐप कुछ भी प्रिंट नहीं करता है


160

मेरे पास पायथन (2.7) ऐप है जो मेरे डॉकफाइल में शुरू किया गया है:

CMD ["python","main.py"]

main.py कुछ स्ट्रिंग्स को प्रिंट करता है जब इसे शुरू किया जाता है और बाद में लूप में चला जाता है:

print "App started"
while True:
    time.sleep(1)

जब तक मैं कंटेनर को -it फ्लैग के साथ शुरू करता हूं, तब तक सब कुछ उम्मीद के मुताबिक काम करता है:

$ docker run --name=myapp -it myappimage
> App started

और मैं बाद में लॉग के माध्यम से एक ही आउटपुट देख सकता हूं:

$ docker logs myapp
> App started

अगर मैं -d ध्वज के साथ एक ही कंटेनर चलाने की कोशिश करता हूं, तो कंटेनर सामान्य रूप से शुरू होता है, लेकिन मैं कोई आउटपुट नहीं देख सकता:

$ docker run --name=myapp -d myappimage
> b82db1120fee5f92c80000f30f6bdc84e068bafa32738ab7adb47e641b19b4d1
$ docker logs myapp
$ (empty)

लेकिन कंटेनर अभी भी लगता है;

$ docker ps
Container Status ...
myapp     up 4 minutes ... 

संलग्न कुछ भी प्रदर्शित नहीं करता है:

$ docker attach --sig-proxy=false myapp
(working, no output)

किसी भी विचार क्या गलत हो रहा है? क्या "प्रिंट" पृष्ठभूमि में चलने पर अलग तरह से व्यवहार करता है?

डॉकर संस्करण:

Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.2
Git commit (client): a8a31ef
OS/Arch (client): linux/arm
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.2
Git commit (server): a8a31ef

जवाबों:


265

अंत में मुझे डॉकटर में डीमॉनेटाइज्ड चलने पर पायथन आउटपुट देखने का एक उपाय मिला, इसके लिए @Hmetalpbalkan पर धन्यवाद GitHub । आगे के संदर्भ के लिए स्वयं इसका उत्तर देना

के साथ unbuffered आउटपुट का उपयोग करना

CMD ["python","-u","main.py"]

के बजाय

CMD ["python","main.py"]

समस्या हल करता है; आप आउटपुट (दोनों, stderr और stdout) को देख सकते हैं

docker logs myapp

अभी!


2
-मुझे लगता है कि यह मेरे लिए काम कर रहा है, लेकिन क्या यह वास्तव में क्या करता है, इसके विवरण के साथ कहीं कुछ प्रलेखन है?
थोड़ा गीक

7
अन्य उत्तर द्वारा सुझाए गए के रूप में, आप वातावरण चर सेट करने का प्रयास कर सकते हैं ENV PYTHONUNBUFFERED=0मामले में -uझंडा काम नहीं करता।
Farshid T

1
मेरी भी यही समस्या थी। अधिक विस्तृत विवरण के लिए, stackoverflow.com/a/24183941/562883
जोनाथन


1
Python3 पर एक सपने की तरह काम करता है, जबकि PYTHONUNBUFFERED = 0 की मदद नहीं करता है।
लेच मिग्डल

71

मेरे मामले में, पायथन को चलाने से -uकुछ भी नहीं बदला। हालाँकि, PYTHONUNBUFFERED=0पर्यावरण चर के रूप में क्या चाल थी :

docker run --name=myapp -e PYTHONUNBUFFERED=0 -d myappimage

6
मेरे मामले में, जोड़ने से -e PYTHONUNBUFFERED=0मदद मिलती है।
डेविड एनजी

1
धन्यवाद! मैं घंटों तक एक दीवार से अपना सिर पीटता रहा, और साथ काम करने के लिए भी लॉग नहीं मिला -u। आपके समाधान ने इसे मेरे लिए
डॉक

2
मुझे लगता है कि यह एक बेहतर उपाय है, कि हमें आउटपुट देखने के लिए
डॉक

2
यह बहुत धन्यवाद है। यह ध्यान देने योग्य है कि यह केवल डॉक्स PYTHONUNBUFFERED के
एक स्टार

डॉकटर-कम्पोज़ इंटरफ़ेस के लिए काम किया। कभी भी अनुमान नहीं लगाया होगा
1

24

मेरे लिए यह एक सुविधा है, बग नहीं। एक छद्म-TTY के बिना वहाँ stdout करने के लिए कुछ भी नहीं है। तो एक सरल उपाय है कि आप अपने चलने वाले कंटेनर के लिए एक छद्म-TTY आवंटित करें:

$ docker run -t ...

यह प्रश्न का उत्तर प्रदान नहीं करता है। किसी लेखक से स्पष्टीकरण मांगने या उसका अनुरोध करने के लिए, उनके पोस्ट के नीचे एक टिप्पणी छोड़ दें।
राष्ट्रपति जेम्स के। पोल्क

@JamesKPolk, क्या यह अब बेहतर है?
पीटर सेना

डॉकटर को छद्म और stderr के लिए आबंटित किए जाने के लिए छद्म tty की आवश्यकता नहीं होती है
मैट

3
tty: trueरचना में भूमि
गहरीकरण

15

इस लेख को देखें जो व्यवहार के विस्तार का कारण बताते हैं:

बफ़रिंग के लिए आमतौर पर तीन मोड हैं:

  • यदि कोई फ़ाइल डिस्क्रिप्टर अप्रभावित है, तो कोई बफरिंग नहीं होती है, और फ़ंक्शन कॉल जो डेटा को पढ़ते हैं या लिखते हैं, वे तुरंत होते हैं (और ब्लॉक हो जाएंगे)।
  • यदि कोई फ़ाइल डिस्क्रिप्टर पूरी तरह से बफ़र्ड है, तो एक निश्चित आकार के बफर का उपयोग किया जाता है, और बफर से बस पढ़ने या लिखने के लिए कॉल पढ़ने या लिखने। जब तक यह भर नहीं जाता तब तक बफर को फ्लश नहीं किया जाता है।
  • यदि कोई फ़ाइल डिस्क्रिप्टर लाइन-बफ़र है, तो बफ़रिंग तब तक प्रतीक्षा करता है जब तक कि वह एक नया वर्ण नहीं देखता। इसलिए डेटा बफर और बफर करेगा जब तक कि \ n दिखाई नहीं देता है, और फिर उस समय में सभी डेटा को बफर किया जाता है। वास्तविकता में आमतौर पर बफर पर एक अधिकतम आकार होता है (बस पूरी तरह से बफर वाले मामले में), इसलिए नियम वास्तव में "बफर की तरह है जब तक कि एक नया चरित्र नहीं देखा जाता है या 4096 बाइट्स डेटा सामने आते हैं, जो भी पहले होता है"।

और GNU libc (glibc) बफरिंग के लिए निम्नलिखित नियमों का उपयोग करता है:

Stream               Type          Behavior
stdin                input         line-buffered
stdout (TTY)         output        line-buffered
stdout (not a TTY)   output        fully-buffered
stderr               output        unbuffered

इसलिए, यदि डॉक्यूमेंट डॉक्यूमेंट-t से उपयोग किया जाता है , तो यह एक छद्म टैटी को आवंटित करेगा, फिर बनता है , इस प्रकार एक-लाइन आउटपुट को देख सकता है।stdoutline-buffereddocker run --name=myapp -it myappimage

और, यदि सिर्फ उपयोग -d, कोई tty आवंटित किया गया था, तो, stdoutहै fully-buffered, एक पंक्ति App startedनिश्चित रूप से बफर फ्लश करने में सक्षम नहीं।

फिर, उपयोग -dtकरने के लिए make stdout line bufferedया ऐड -uअजगर में करने के लिए flush the bufferजिस तरह से यह तय करने के लिए है।


8

यदि आप अपने प्रिंट आउटपुट को अपने फ्लास्क आउटपुट में जोड़ना चाहते हैं docker-compose up, तो रनिंग फ़ाइल को अपने डॉकटर में निम्नलिखित जोड़ें।

web:
  environment:
    - PYTHONUNBUFFERED=1

https://docs.docker.com/compose/environment-variables/


6

आप अलग छवि पर लॉग यदि आप बदल सकते हैं printकरने के लिए logging

main.py:

import time
import logging
print "App started"
logging.warning("Log app started")
while True:
    time.sleep(1)

Dockerfile:

FROM python:2.7-stretch
ADD . /app
WORKDIR /app
CMD ["python","main.py"]

1
अच्छा। टिप: पाइथन 3 का उपयोग करें
adhg

प्रश्न पायथन 2 (कोष्ठक के बिना प्रिंट स्टेटमेंट) में है इसलिए यहाँ 2 का उपयोग किया जा रहा है। हालाँकि यह Python3.6 पर ठीक वैसा ही व्यवहार है इसलिए एक टिप के लिए धन्यवाद;)
द हॉग

6

चूँकि मैंने यह उत्तर अभी तक नहीं देखा है:

आप इसे प्रिंट करने के बाद भी स्टडआउट फ्लश कर सकते हैं:

import time

if __name__ == '__main__':
    while True:
        print('cleaner is up', flush=True)
        time.sleep(5)

1
यह मेरे लिए पूरी तरह से काम करता है, बेवकूफ है कि यह वहाँ रहने की जरूरत है, लेकिन अब महान काम करता है।
jamescampbell


3

एक त्वरित सुधार के रूप में, यह प्रयास करें:

from __future__ import print_function
# some code
print("App started", file=sys.stderr)

यह मेरे लिए काम करता है जब मैं उसी समस्याओं का सामना करता हूं। लेकिन, ईमानदार होने के लिए, मुझे नहीं पता कि यह त्रुटि क्यों होती है।


पारितोषिक के लिए धन्यवाद! अपने संस्करण के साथ सभी प्रिंटों को बदलने की कोशिश की, दुर्भाग्य से यह मेरे लिए काम नहीं करता था, फिर भी डॉक लॉग्स (sys.stderr / sys.stdout के बीच कोई परिणाम नहीं दिखाई देता है) के माध्यम से कोई भी आउटपुट नहीं मिल सकता है। क्या यह एक डॉक बग है?
jpdus

मेरा उत्तर देखें , इसका कारण यह है: स्टैडर अप्रभावित था, इसलिए आप इसे अपने समाधान के साथ ठीक कर सकते हैं।
9

1

मुझे PYTHONUNBUFFERED=1django runserver से आउटपुट देखने के लिए अपने docker-compose.yml फ़ाइल में उपयोग करना पड़ा ।


0

आमतौर पर, हम इसे एक विशिष्ट फ़ाइल पर होस्ट करते हैं (होस्ट से वॉल्यूम बढ़ाकर और इसे उस फ़ाइल पर लिखकर)।

-T का उपयोग करके एक tty जोड़ना भी ठीक है। आपको इसे डॉक लॉग में लेने की आवश्यकता है।

बड़े लॉग आउटपुट का उपयोग करते हुए, मेरे पास बफ़र स्टोरिंग के साथ कोई भी मुद्दा नहीं था, इसे डॉकर लॉग में डाले बिना।


-1

यदि आप इसके बजाय docker-composeकेवल सामान्य उपयोग नहीं कर रहे हैं docker, तो आप इसे अपने लिए जोड़ सकते हैं Dockerfileजो एक फ्लास्क ऐप को होस्ट कर रहा है

ARG FLASK_ENV="production"
ENV FLASK_ENV="${FLASK_ENV}" \
    PYTHONUNBUFFERED="true"

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