Python子进程不打印真实的时间

7tofc5zh  于 2024-01-05  发布在  Python
关注(0)|答案(1)|浏览(136)

test.py

  1. import time
  2. for x in range(0, 10, 1):
  3. print(x)
  4. time.sleep(1)

字符串
python test.py打印真实的时间,即每秒一个数字

  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9


现在,我想通过下面的子进程在另一个名为run.py的脚本中运行test.py
run.py

  1. import subprocess
  2. from subprocess import PIPE, STDOUT
  3. proc = subprocess.Popen(
  4. 'python test.py',
  5. stdout=PIPE,
  6. stderr=STDOUT,
  7. shell=True,
  8. encoding="utf-8",
  9. errors="replace",
  10. universal_newlines=True,
  11. text=True,
  12. bufsize=1,
  13. )
  14. while (realtime_output := proc.stdout.readline()) != "" or proc.poll() is None:
  15. print(realtime_output.strip(), flush=True)


当我运行python run.py时,输出不是真实的时间(没有每秒打印的数字)
奇怪的是,如果我将test.py中的代码修改为print(x, flush=True),那么python run.py每秒打印一次。
有没有办法在run.py中通过subprocess输出真实的时间而不修改test.py的打印语句?

zengzsys

zengzsys1#

bufsize=1正在更改父进程proc.stdout文件句柄中的 input 缓冲区。它不会以任何方式影响子进程的 output 缓冲区。当Python的stdout连接到管道而不是终端时,它会自动进入块缓冲模式。
test.py更改为使用print(x, flush=True),它将刷新每个print上的输出缓冲区,无论是连接到终端、文件还是管道,您在父进程中禁用缓冲区的工作将按预期生效。
或者,将子进程的run改为将-u传递给python,使其不受缓冲,例如'python -u test.py'。这将完全禁用输出缓冲,消除对flush=True的需要(但它会使程序只需要flush=True * 有时 *,但写出来很多没有它,运行得更慢)。
作为旁注:几乎没有理由使用shell=True(您可以/应该使用它的唯一时间是如果命令行的任何组件都不来自不受信任的数据源,例如用户,并且您需要使用shell内置和/或shell元字符,并且您确信您没有意外地使用任何这样的元字符)。您的子进程将避免不必要的 shell Package 层(这可能会引入额外的缓冲复杂性),通过将'python test.py'更改为['python', 'test.py']['python', '-u', 'test.py']用于无缓冲输出),并删除shell=True,,一切都应该更有效,更安全地运行。
你也可以去掉universal_newlines=True,,因为text=True的意思是完全一样的;如果你只支持允许text=True的Python版本,那么universal_newlines=True对你来说毫无用处。

相关问题