Thread
和Greenlet
在交互式环境中具有不同的行为。在某些情况下,需要对主事件循环进行修改。
Greenlet
来自于Python的一个并发任务模块gevent
。它具有与Python(pthread)分开的内部上下文切换机制,并且并发性能非常好(以我的经验)。但是,Greenlet
存在某些问题,例如如果未进行猴子补丁(在gevent
模块中),则会在阻止C系统调用和套接字交互时进行阻塞。
为了使greenlets
正常工作,需要对主事件循环进行修补... 如果您在交互式环境中生成greenlet
,它将无法切换上下文并执行。我忘了如何动态修改主事件循环(稍后补充)。
失败的示例:
In [1]: from gevent.greenlet import Greenlet
In [2]: def print_hi():
...: print 'hi'
...:
In [3]: print_hi()
hi
In [4]: g = Greenlet(print_hi)
In [5]: g.start()
编辑:
在查看了这个项目的一些代码后,这里是我们如何通过黑客手段使用 gevent 来修改 ipython 输入钩子的方法。
import sys
import select
import gevent
def stdin_ready():
infds, outfds, erfds = select.select([sys.stdin], [], [], 0)
if infds:
return True
else:
return False
def inputhook_gevent():
try:
while not stdin_ready():
gevent.sleep(0.001)
except KeyboardInterrupt:
pass
return 0
# install the gevent inputhook
from IPython.lib.inputhook import inputhook_manager
inputhook_manager.set_inputhook(inputhook_gevent)
inputhook_manager._current_gui = 'gevent'
# First import the embeddable shell class
from IPython.frontend.terminal.embed import InteractiveShellEmbed
修补示例:
In [6]: def say_hi():
...: print "hi"
...:
In [7]: g = gevent.greenlet.Greenlet(say_hi)
In [8]: g.start()
In [9]: hi <-- Cursor is here so it printed hi
看起来你正在与硬件进行交互,这就引出了REPL和脚本之间最明显的区别:
在脚本中运行的命令会尽快立即执行,而REPL则等待人类输入。
也就是说,可能存在一个时序问题,硬件可能在执行上一个命令后不会那么快准备好下一个命令。
time.sleep(1)
。但是结果仍然一样。所以,虽然这个答案很好,但似乎并不能解决另一个问题。 - Andrew看一下这行代码
PCO_api = ctypes.oledll.LoadLibrary("SC2_Cam")
如果您可以使用完整路径来加载LoadLibrary
python myscript.py
和python -i
以及手动键入相同命令之间的区别。如果您对自己的断言(当前工作目录、路径和环境变量将相同)有信心,我会编辑我的问题,删除误导性陈述。 - Andrew