我用python3.6.8从Linux终端运行一个脚本,当我试图用函数定义扩展它时,脚本开始失败。我把它细化到基本的部分,发现当代码中有一个函数定义后跟一个print语句时,设备无法连接,但是当有print语句后跟函数定义时,设备就不能连接了。在
此代码成功连接到设备(并断开连接):import DeviceInterface
device_class = DeviceInterface.Device()
print()
def dummy_function_that_does_nothing():
pass
with device_class:
pass
此代码交换了函数定义和print语句,给出了一个设备连接错误:
^{pr2}$
这些示例是正在运行的脚本的确切文件内容(本文没有添加或省略任何内容)。DeviceInterface模块是一个围绕基于C的.so库的ctypes包装器。这个库使用的是aravisv0.6.4。连接失败是由调用arv_camera_new()返回的空指针引起的。在
我希望上面两个版本的代码没有区别。在Python或Linux库中似乎有一些我不理解的更深层次的东西。在
为什么print()出现在函数定义之前而不是之后?我有解决办法,所以我的问题不是围绕如何让我的代码工作,而是在一个较低的层次上理解为什么Python的工作方式会有所不同。我很震惊这两个版本的代码之间会有区别。在
再现性
不幸的是,如果没有我无权分发的库,我还没有找到复制问题的方法。我希望有人偶然发现了这一点,他知道当函数定义后跟print语句(与print语句后跟函数定义)时,Python的行为会有什么不同。如果我理解这两个版本的代码之间的区别,我可能会想出一个更通用的方法来重现这个问题。在
我试过的其他事情我在不同的地方插入了延迟,但都没有影响设备是否成功连接,所以它似乎不像我最初怀疑的那样是时间问题。在
我多次尝试运行这两个版本,这个问题一直与函数定义和print语句的顺序(而不是能够随机连接)联系在一起。在
如果我完全删除print语句,不管函数定义放在哪里,它都会成功。在
我想这可能与垃圾回收杀死一个套接字有关。我尝试用禁用垃圾回收gc.禁用()在脚本开头,但它没有更改行为。
此代码添加了附加函数定义,成功连接:
^{3}$
此代码添加了一个附加的函数定义和另一个print语句,无法连接:import DeviceInterface
device_class = DeviceInterface.Device()
def dummy_function_that_does_nothing():
pass
print()
def dummy_function_that_does_nothing_again():
pass
print()
with device_class:
pass将print语句更改为print(flush=True)或print(系统标准)没有更改功能。但是,print(end=“”)导致问题消失。在
使用无缓冲的stdin/stdout/stderr运行python(python3-uodd\u行为_测试.py)导致了失败。在