【发布时间】:2016-05-16 06:31:33
【问题描述】:
我有一个相当复杂的基于套接字 ( ZeroMQ - REQ/REP ) 的 python 程序,我想通过在同一台机器上运行一个简单的套接字脚本来验证它是否正常工作。
测试脚本是这样的。
import subprocess
import zmq
import json
# ...
for call, response in zip(test_calls, expected_responses):
p = subprocess.Popen(['python', 'main.py'], stdout=subprocess.PIPE)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.setsockopt(zmq.RCVTIMEO, 1000)
socket.connect("tcp://localhost:8084")
socket.send_string(json.dumps(call))
r = json.loads(socket.recv_string())
assert r == response
p.terminate()
socket.close()
(可能值得注意的是,它实际上是在nose2中使用这样的测试实现的,但我觉得这超出了这个问题的范围,并且确实会使样本复杂化。这几乎总结了测试中发生的事情)。
85% 的时间,这会奏效,一切都会过去。嗬嗬!另外 15% 的时间,我在 r = json.loads(socket.recv_string()) 线上得到一个 zmq.error.Again: Resource temporarily unavailable(如果我没有设置 zmq.RCVTIMEO,它就会挂起)。
想知道这是否是一个计时过程(子进程无法及时启动/停止),我在这个地方打了几个 time.sleep() 电话,但它似乎没有做任何事情。
我在套接字部分和pdb'd 之后放置了一个catch,检查了python 子进程的stdout。我在应用程序中有一些 print 语句,每次通过套接字调用和响应时都会打印到 stdout,但它没有收到任何输入,所以 recv 当然会超时。
我以前从未遇到过 zmq 的这类问题,所以我认为这可能与使用这样的子进程有关。有谁知道问题可能是什么以及如何解决?
谢谢。
更新:所以看起来进程没有终止(尽管在主应用程序中使用了signal.signal(signal.SIGTERM, close_app) 信号)。这会导致对通过 zmq 进行通信的活动进程的混淆吗?最初调用 p.kill() 而不是 p.terminate() 似乎可以解决问题,尽管它仍然以同样的方式失败了一两次。
更新 2: 似乎正在工作,直接调用命令 kill:
subprocess.call(['kill', str(p.pid)])
counter = 0
while p.poll() is None:
time.sleep(0.1)
counter += 1
if counter > 20:
p.kill()
在大多数情况下,这似乎可以优雅地关闭它。
【问题讨论】:
-
您能否确认,一般场景适用于
zmq.REP对等点的“非子进程”模式(独立进程),即.bind()-s 在同一个tcp://localhost:8084上?
标签: python python-3.x subprocess zeromq pyzmq