我有一个Python脚本(popen.py
),它作为子进程运行另一个Python脚本(counter.py
),并将输出重定向到/tmp/counter.log
。我使用的代码是:
/tmp/counter.py
#!/usr/bin/env python2
import time
i = 0
while True:
print i
i +=1
time.sleep(1)
/tmp/popen.py
#!/usr/bin/env python2
import subprocess
f = open("/tmp/counter.log", "a+")
p = subprocess.Popen("/tmp/counter.py", stdout=f, stderr=f, bufsize=1)
然而,当我运行popen.py
时,子进程被创建并保持运行状态,但是在输出达到4096字节之前,/tmp/counter.log
中没有任何内容被写入,然后似乎被刷新到文件中。
有没有办法让我的子进程按行写入日志文件,而不修改counter.py
脚本本身?
我不想修改counter.py
的原因是子进程可能并不总是运行Python脚本。我尝试使用一个小型可执行文件(用C编写)运行相同的操作,但是仍然存在同样的问题。
我尝试编写了一个自动刷新文件的包装器,并将其用于stdout
,如此处所述,但也不起作用。
我已经使用lsof
和strace
进行了一些调试,以下是我找到的信息:
lsof(文件描述符)
手动运行/tmp/counter.py
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python2 629 daniel 0u CHR 136,0 0t0 3 /dev/pts/0
python2 629 daniel 1u CHR 136,0 0t0 3 /dev/pts/0
python2 629 daniel 2u CHR 136,0 0t0 3 /dev/pts/0
通过 /tmp/popen.py 运行 /tmp/counter.py
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python2 638 daniel 0u CHR 136,0 0t0 3 /dev/pts/0
python2 638 daniel 1u REG 202,0 0 768 /tmp/counter.log
python2 638 daniel 2u REG 202,0 0 768 /tmp/counter.log
strace(在while循环期间的系统调用)
手动运行/tmp/counter.py
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(1, "11\n", 3) = 3
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(1, "12\n", 3) = 3
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(1, "13\n", 3) = 3
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(1, "14\n", 3) = 3
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(1, "15\n", 3) = 3
通过 /tmp/popen.py 运行 /tmp/counter.py
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
...
write(1, "11\n12\n13\n14\n15\n16\n17\n18\n"..., 4096) = 4096
Popen()
构造函数 的文档称将bufsize
设置为 0 意味着无缓冲,我认为这正是你想要的。 - martineau