【发布时间】:2017-05-19 19:02:09
【问题描述】:
我有一个程序,我想做两件事:
与服务器交互并响应来自服务器的事件。我正在使用twisted 进行此操作。
为用户提供命令行提示符,用户可以在其中发出其他命令。到目前为止,我正在使用 python cmd 模块。
似乎除了拥有两个线程之外别无选择,因为 readline 只有一个阻塞接口,需要处理诸如自动完成之类的事情。另一方面,Twisted 必须连续运行反应堆。
现在的问题是,为此处理 Ctrl-C 似乎非常困难。简单的解决方案似乎是让命令行在主线程中运行,并且只使用 reactor.callFromThread 与程序的其余部分进行每次交互。这非常容易,因为覆盖 Cmd.onecmd 可以以通用方式执行此操作。但是,当我尝试在线程中生成反应器时,
t = Thread(target=reactor.run)
t.start()
我立即得到一个异常
File "/usr/lib/python3.6/signal.py", line 47, in signal
handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
builtins.ValueError: signal only works in main thread
每个使用twisted的人都坚持twisted reactor应该在主线程中运行,因为这样会更好。
当尝试这样做并在主线程中扭曲运行时,它将捕获 Ctrl-C,退出反应器,我被一个不退出的线程卡住,因为在 cmdloop 中调用 input()不返回。我尝试寻找解决方案以及如何摆脱 input() 调用,但每个人都坚持命令行界面应该在主线程中运行。
我发现的一个可能的选择是将twisted作为主线程运行并使输入线程成为守护进程,因此它应该在反应器退出时退出,但是守护进程标志没有改变任何东西(主线程时线程没有退出线程做了)。此外,这可能很危险,因为线程在被杀死时可能正在做一些重要的事情。
有什么办法可以解决吗?
【问题讨论】:
-
Twisted examples 页面上有一个名为
stdiodemo.py的示例,这应该是一个很好的起点。这个例子展示了如何在没有线程的情况下做你想做的事情。
标签: python twisted python-multithreading python-cmd