Python脚本运行与交互式命令行运行的区别

4 投票
2 回答
924 浏览
提问于 2025-04-16 06:07

我正在调试一个关于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 个回答

1

在进行异步或并发操作时(比如多线程或多进程),有些事情是需要注意的。比如,当你在交互式运行Python时,其实并没有一个主循环。虽然__name__被设置为__main__,但在这里定义或执行的内容可能并不总是可用。尤其是在多进程的情况下,甚至在某些多线程的情况下,对象的状态可能不会在不同的进程或线程之间共享。

这种情况可能会让人感到困惑,严重时甚至会带来危险。在调试时,养成一个好习惯就是给你的线程命名,并结合使用Python的logging模块,这样可以帮助你跟踪后台发生的事情。

1

Python的交互式解释器不是线程安全的。这意味着,如果你发送一个会阻塞的命令,整个解释器就会卡住。

想了解为什么会这样,可以看看这篇文章(简单来说,就是IDLE和线程不太兼容)。至于怎么解决这个问题,建议使用控制台,而不是IDLE的图形界面。或者,你也可以直接写一个脚本来运行。

撰写回答