Что такое стандартные потоки, если нет окна терминала/консоли для интерпретатора python?

В Ubuntu Desktop (Unity), когда script помечен как исполняемый файл, а затем я нажимаю на файл, я получаю всплывающее окно, подобное изображению на изображении:

введите описание изображения здесь

pyscript.py - это исполняемый файл Python script с помощью shebang: #!/usr/bin/python где /usr/bin/python - это путь к интерпретатору Python. Поскольку я не запускаю этот процесс в терминальном окне, потому что я просто нажал "Запустить", я думал, что вначале не было бы стандартных потоков для процесса; Когда я экспериментировал больше, я понял, что доступны все стандартные потоки:

pyscript.py

#!/usr/bin/python3
import sys, os
f = file=open("output.txt", "w")
print(sys.stdout, sys.stdin, sys.stderr, sep='\n', file=f)

output.txt

<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
<_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>

Что вызывает вопрос, нет ли оконного окна в фоновом режиме, к чему подключены sys.stdout, stdin и stderr? Технически, запуск Python без консольного окна под Windows с .pyw Я получаю тот же результат.

Взгляните на этот вопрос: pythonw.exe или python.exe?

В одном из ответов говорится следующее:

Стандартные потоки sys.stdin, sys.stdout и sys.stderr НЕ доступны.

То, что стандартные потоки недоступны, не кажется истинным, когда я тестирую это с помощью Python 2.7 в Windows 10, щелкнув файл .pyw, хотя в реестре Windows файлы .pyw связаны с Python 2. X, который запускает pythonw.exe на моей машине.

Этот вопрос - беспорядок Unix/Windows!

Ответ 1

Как уже упоминалось, вопрос не является специфичным для Python. Когда процесс порождается, родительская обязанность - устанавливать описатели дочерних файлов (или разрешать их наследование).

Итак, это даже не специфичный для ОС, а действительно специфический для приложения. Например, у вас может быть другой anser для Gnome и KDE. Или при выполнении файла из Windows Explorer или 7-Zip (я думаю, я знаю, как это работает в Unix, не так уверенном в Windows). Различные приложения, создающие процесс, могут создавать различные варианты.

В Linux вы можете узнать, запустив lsof в процессе python, который отобразит открытые файлы и скажет вам, где именно идет ваша stdout. Здесь ваш код изменился, чтобы сделать именно это:

#!/usr/bin/env python

# vi: ai sts=4 sw=4 et

import sys, os, pprint
import subprocess

f = open("/tmp/output.txt", "w")

for stream in (sys.stdout, sys.stdin, sys.stderr):
    print (stream, file=f)
    print ("STTY?", stream.isatty(), file=f)
    print ("fileno:", stream.fileno(), file=f)
    print ("name:", stream.name, file=f)

#    print (pprint.pprint(dir(stream)), file=f)
    print (file=f)

subprocess.call ("lsof -p %s" % os.getpid(), stdout = f, shell = True)

Фактически важна только последняя строка. См. Вывод для обычного запуска:

(...)
test.py 29722 xxx    0u   CHR  136,4      0t0      7 /dev/pts/4
test.py 29722 xxx    1u   CHR  136,4      0t0      7 /dev/pts/4
test.py 29722 xxx    2u   CHR  136,4      0t0      7 /dev/pts/4

И при перенаправлении вывода в файл:

(...)
test.py 29728 xxx    0u   CHR  136,4      0t0       7 /dev/pts/4
test.py 29728 xxx    1w   REG   0,38        0 2070222 /tmp/asdf.txt
test.py 29728 xxx    2u   CHR  136,4      0t0       7 /dev/pts/4

Посмотрите, что файл №1 изменился? То же самое произойдет, когда вы запустите его из Unity, сообщив, где это происходит.

Я точно не воспроизвел вашу проблему, так как мой файловый менеджер Gnome 3 не запускает сценарии, подобные этому, и я бы не стал заглядывать в него, но мне любопытно узнать, где вы находитесь.