Python脚本运行与交互式命令行运行的区别
我正在调试一个关于ctypes封装Windows DLL的问题,发现通过交互式命令行(python或ipython)运行测试时,和以非交互方式运行脚本时,结果有些不同。
我想知道这些差异的原因是什么?
具体来说,当我在交互式环境中运行一个简单的测试时,调用DLL的操作会卡住,永远不会返回,而完全相同的代码在脚本中运行时却没有这个问题。
为了更清楚地说明我的意思,假设你有以下代码:
from foobar import bar, foo
bar(foo(1,2,3))
当把它放在一个文件里,比如叫“myfoo.py”,然后通过“python myfoo.py”执行时,上面的代码会按预期运行。然而,如果你在python/ipython的命令行中输入这段代码,行为就会不同(在我的情况下,调用ctypes.WinDLL函数时会卡住)。
一些额外的细节:
我在这两种情况下使用的是相同的解释器和PYTHONPATH。被封装的DLL是Canon EDSDKv2.9,这是一个用于远程控制相机的SDK。问题总是在DLL中出现,而不是在python代码中。
当初始化时,我的EDSDK封装会启动一个线程,它的运行方法看起来像这样:
def run(self):
sys.coinit_flags = 0 #use multithreaded mode
from pythoncom import PumpWaitingMessages
#^^ done here so this thread is correctly initialised
error(EDSDK.EdsInitializeSDK())
self.EDSDK_initialised = True
while self.active:
PumpWaitingMessages()
sleep(self.msg_sleep_time)
error(EDSDK.EdsTerminateSDK())
这个线程的主要目的是初始化SDK,处理消息,并允许其他线程调用封装的方法。
注意:在之前的EDSDK版本中,这个方法在交互式和非交互式环境下都能正常工作。现在的问题只出现在最新版本的EDSDK中。
我怀疑这可能与线程有关(所以我提供了这段代码),但在网上找不到任何支持我怀疑的信息。
所以,有人知道在交互式和非交互式运行python时有什么不同吗?可能与Windows线程有关吗?在这个时候,任何帮助,甚至是随便的猜测,我都非常感激,因为我完全被难住了! :)
2 个回答
在进行异步或并发操作时(比如多线程或多进程),有些事情是需要注意的。比如,当你在交互式运行Python时,其实并没有一个主循环。虽然__name__
被设置为__main__
,但在这里定义或执行的内容可能并不总是可用。尤其是在多进程的情况下,甚至在某些多线程的情况下,对象的状态可能不会在不同的进程或线程之间共享。
这种情况可能会让人感到困惑,严重时甚至会带来危险。在调试时,养成一个好习惯就是给你的线程命名,并结合使用Python的logging
模块,这样可以帮助你跟踪后台发生的事情。
Python的交互式解释器不是线程安全的。这意味着,如果你发送一个会阻塞的命令,整个解释器就会卡住。
想了解为什么会这样,可以看看这篇文章(简单来说,就是IDLE和线程不太兼容)。至于怎么解决这个问题,建议使用控制台,而不是IDLE的图形界面。或者,你也可以直接写一个脚本来运行。