Bar*_*art 73 shell python stdout
尝试将 Python 脚本中的 stdout 写入文本文件 ( python script.py > log) 时,会在命令启动时创建文本文件,但在 Python 脚本完成之前不会写入实际内容。例如:
脚本.py:
import time
for i in range(10):
print('bla')
time.sleep(5)
Run Code Online (Sandbox Code Playgroud)
使用 调用时每 5 秒打印到标准输出python script.py,但是当我调用 时python script.py > log,日志文件的大小保持为零,直到脚本完成。是否可以直接写入日志文件,以便您可以跟踪脚本的进度(例如使用tail)?
编辑事实证明,这样python -u script.py做的技巧,我不知道标准输出的缓冲。
Dig*_*uma 81
发生这种情况是因为通常当进程 STDOUT 被重定向到终端以外的东西时,输出会被缓冲到一些操作系统特定大小的缓冲区(在许多情况下可能是 4k 或 8k)。相反,当输出到终端时,STDOUT 将被行缓冲或根本不缓冲,因此您会在\n每个字符或每个字符之后看到输出。
您通常可以使用该stdbuf实用程序更改 STDOUT 缓冲:
stdbuf -oL python script.py > log
Run Code Online (Sandbox Code Playgroud)
现在,如果您tail -F log,您应该在生成时立即看到每一行输出。
或者,每次打印后显式刷新输出流应该达到相同的效果。看起来sys.stdout.flush()应该在 Python 中实现这一点。如果您使用的是 Python 3.3 或更新版本,则该print函数还有一个flush关键字可以执行此操作:print('hello', flush=True).
hee*_*ayl 55
这应该可以完成这项工作:
import time, sys
for i in range(10):
print('bla')
sys.stdout.flush()
time.sleep(5)
Run Code Online (Sandbox Code Playgroud)
由于stdout默认情况下Python 会缓冲,这里我已经用来sys.stdout.flush()刷新缓冲区。
另一解决方案是使用-u的(未缓冲的)开关python。因此,以下内容也将执行:
python -u script.py >> log
Run Code Online (Sandbox Code Playgroud)
Ser*_*nyy 19
使用 python 自己的无缓冲输出选项的主题的变化是#!/usr/bin/python -u用作第一行。
由于#!/usr/bin/env python这个额外的参数不起作用,所以或者,可以PYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt分两步运行或完成:
$ export PYTHONUNBUFFERED=1
$ ./myscript.py
Run Code Online (Sandbox Code Playgroud)
Bak*_*riu 14
你应该传递flush=True给print函数:
import time
for i in range(10):
print('bla', flush=True)
time.sleep(5)
Run Code Online (Sandbox Code Playgroud)
根据文档,默认情况下,print不强制执行任何有关刷新的操作:
输出是否缓冲通常由文件决定,但如果
flush关键字参数为真,则流被强制刷新。
sys的 strems文档说:
交互时,标准流是行缓冲的。否则,它们像常规文本文件一样被块缓冲。您可以使用
-u命令行选项覆盖此值。
如果您坚持使用古老版本的python,则必须调用流的flush方法sys.stdout:
import sys
import time
for i in range(10):
print('bla')
sys.stdout.flush()
time.sleep(5)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
134641 次 |
| 最近记录: |