对于测试我想在Linux上启动一个长期运行的Python 3脚本,捕获它的一些输出,检查它是否符合预期并再次杀死它。
我只是想让普通框架现在正常运作。
当我运行以下代码时,我希望输出包含line = "0"
- python脚本只打印出一个递增的整数序列,每秒一个。相反,完全跳过for
循环。
import subprocess
from tempfile import NamedTemporaryFile
import time
import unittest
import asynchronousfilereader
class TestProcessSpawning(unittest.TestCase):
def test_spawning_counter(self):
counter_code = \
"""
import time
i = 0
while True:
print(i)
i = i + 1
time.sleep(1)
"""
with NamedTemporaryFile(mode="w", suffix='.py', delete=False)\
as temp_file:
temp_file.write(counter_code)
file_name = temp_file.name
# proc = subprocess.Popen(['ping', 'localhost'],
# stdout=subprocess.PIPE, close_fds=True)
proc = subprocess.Popen(['python3', file_name],
stdout=subprocess.PIPE, close_fds=True)
time.sleep(3)
assert proc.returncode is None # None => still running
reader = asynchronousfilereader.AsynchronousFileReader(proc.stdout)
time.sleep(3) # give it a chance?
for line in reader.readlines():
print('line = "{}"'.format(line))
break # just grab first one
proc.kill()
但是,如果我将['python3', file_name]
更改为['ping', 'localhost']
我做从ping获取一行输出(我在Linux上运行,因此ping
继续生成输出,直到你停止它。)
知道为什么这似乎适用于其他类型的子进程而不适用于python?
注意:
asynchronousfilereader
python3 <temp_file_name>
,脚本会按预期运行,打印0,1,2,...... None
表明进程已运行(即不只是崩溃)unbuffer
运行它:输出没有显示bufsize=1
传递给Popen
:输出未显示-v
标志,我会得到很多输出,包括这个,这表明python试图以交互方式运行,即使我提供了一个文件名:Python 3.5.2(默认,2017年11月23日,16:37:01)
[GCC 5.4.0 20160609] on linux
输入“帮助”,“版权”,“信用”或“许可”以获取更多信息。
答案 0 :(得分:1)
您需要刷新您编写的文件:
with NamedTemporaryFile(mode="w", suffix='.py', delete=False) as temp_file:
temp_file.write(counter_code)
temp_file.flush()
你的程序太短,以至于无法将其从缓冲区中取出,否则你正在运行一个空文件。
我还要确保程序在每次写入时都会刷新;对于未缓冲的标准输出运行python3 -u
或在每次打印时使用flush=True
。这样,您就不必在父程序中添加这么多睡眠。
通过这些更改,单元测试打印
line = "b'0\n'"
以及有关子进程仍在运行且stdout缓冲区在完成之前仍处于打开状态的几个警告。