Как работает перенаправление вывода скрипта python?

Есть скрипт test.py вида
import os
print('Пытаемся запустить файл 1:')
os.system('./1.py')
print('Пытаемся запустить файл 2:')
os.system('./2.py')


При его запуске в командной строке выдача соответствует ожидаемому:

Пытаемся запустить файл 1:
Файл один печатает.
Пытаемся запустить файл 2:
Файл два печатает.


Но если его запустить как ./test.py > 1.txt
В файле 1.txt меняется порядок следования строк:

Файл один печатает.
Файл два печатает.
Пытаемся запустить файл 1:
Пытаемся запустить файл 2:


Почему это так работает и можно ли починить?
  • Вопрос задан
  • 362 просмотра
Решения вопроса 1
trapwalker
@trapwalker Куратор тега Python
Программист, энтузиаст
Или вызывайте вот так:
print(subprocess.getoutput('./1.py'))
Так вы дождётесь полного выхлопа.
Но если выхлопа много, то лучше запускать иначе, чтобы получить выходной пайп и вычитывая его в цикле слать всё на stdout __main__

UPD: Дополню ответ, а то часть оказалась в комментариях.

Такое происходит потом, что при перенаправлении выхлопа в файл происходит буфферизация. Накопительный буффер сбрасывается в файловую систему по факту своего заполнения или принудительно (по команде flush или по факту завершения процесса).

При выхлопе, направленном в терминал, буфферизации нет и всё, что выводится, попадает в терминал сразу.
Но если бы каждый байт писался в файловую систему без буффера, то это быо бы чертовски медленно и заставляло бы постоянно дёргаться картеку (реальную или виртуальную) лочного девайса, на котором у нас файловая система.
Так и получается, что
- сперва в stdout материнского процесса попадает некий текст,
- потом запускаеется дочений процесс и что-то пишет в свой stdout,
- потом дочерний процесс закрывается и сбрасывает накопившийся буффер, который перенаправляется по цепочке в выходной файл,
- потом закрывается материнский процесс и весь его недозаполненный буфер тоже сбрасывается в файл.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Можно обвернуть системный вызов в async функцию и использовать await.
https://realpython.com/async-io-python/#the-asynca...

Добавлено:
а нельзя ли просто сделать вывод в stdout и поточное чтение с вывода:
python prog1.py | python prod2.py
?
Ответ написан
Комментировать
Vindicar
@Vindicar
RTFM!
Скорее всего, проблема в работе с одним файлом через два дескриптора (один - stdout твоего скрипта, второй - stdout вызываемого). Попробуй принудительно сбрасывать данные в файл:
print('Пытаемся запустить файл 1:', flush=True)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
07 мая 2024, в 14:11
4000 руб./за проект
07 мая 2024, в 14:10
10000 руб./за проект
07 мая 2024, в 14:04
1300 руб./за проект