【发布时间】:2018-05-20 04:17:28
【问题描述】:
对于一个测试,我想在 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?
注意事项:
- 此代码使用 pip 提供的
asynchronousfilereader - 如果我只是在 shell 中运行
python3 <temp_file_name>,脚本会按预期运行,打印 0、1、2、... - 几秒钟后
None的进程返回码表明进程正在运行(即不只是崩溃) - 我已尝试按照here 的建议通过
unbuffer运行它:输出没有出现 - 我尝试将
bufsize=1传递给Popen:输出没有出现 - 如果我包含
-v标志,我会得到很多输出,包括这个,这表明 python 正在尝试以交互方式运行,即使我提供了文件名:
Python 3.5.2(默认,2017 年 11 月 23 日,16:37:01)
[GCC 5.4.0 20160609] 在 Linux 上
输入“帮助”、“版权”、“信用”或“许可”以了解更多信息。
【问题讨论】:
-
我更新了重复的目标。您的问题是您没有刷新子进程中的输出缓冲区。使用
-u开关运行,或将flush=True添加到您的print()调用中。 -
请注意,您缺少一些导入(
NamedTemporaryFile、time)并且with ... as语句必须在一行中。 -
@MartijnPieters 我已经尝试过
-u并且刚刚尝试过flush=True。我仍然没有得到输出。感谢您告诉我有关导入问题的信息——我会解决的。 -
我注意到读者线程不再活跃;所以线程中的
line = self._fd.readline()read 调用在第一轮或很快就返回了一个空响应。 -
-v显示 Python 导入的内容,并始终包含版权声明。它没有以交互方式运行任何东西。
标签: python asynchronous subprocess stdout