我遇到一个问题,即导入python模块的对象被破坏,但只有在显式调用sys.exit()
之后才会出现问题。这也是间歇性的。除了“标准”pyusb
模块之外,我已经删除了大部分代码(我已经使用了最新版本)。实际上很少发生。
如果程序调用sys.exit(),则某些对象ID将更改为垃圾值。如果我把它留下来就没有错误!
这真的是Python中的一个错误吗?这似乎不太可能。我做错了什么?
=====主程序“bug_happens.py”
#!/usr/bin/python3
import sys
import usbtmc
scope = usbtmc.Instrument()
print('in Main')
print(' id of usbtmc.usb: 0x{:x}'.format(id(usbtmc.usb)))
print(' id of usbtmc.usb.util: 0x{:x}'.format(id(usbtmc.usb.util)))
print(' id of usbtmc.usb.util.dispose_resources: 0x{:x}'.format(id(usbtmc.usb.util.dispose_resources)))
print()
print('calling Exit()')
sys.exit()
=====非常剥离了usbtmc模块
"""
****** Very stripped down partial Version for debugging a memory corruption issue ******
Python USBTMC driver
Copyright (c) 2012-2017 Alex Forencich
...
"""
import usb.util
class Instrument(object):
def __init__(self, *args, **kwargs):
self.connected = False
print('usbtmc.Instrument created 0x{:x}'.format(id(self)))
print(' id of usb: 0x{:x}'.format(id(usb)))
print(' id of usb.util: 0x{:x}'.format(id(usb.util)))
print(' id of usb.util.dispose_resources: 0x{:x}'.format(id(usb.util.dispose_resources)))
print()
def __del__(self):
print('usbtmc.Instrument.__del__() called for 0x{:x}'.format(id(self)))
print(' id of usb: 0x{:x}'.format(id(usb)))
print(' id of usb.util: 0x{:x}'.format(id(usb.util)))
print(' id of usb.util.dispose_resources: 0x{:x}'.format(id(usb.util.dispose_resources)))
print(' end of usbtmc.Instrument.__del__()')
print()
=============================================== =======
usbtmc.Instrument created 0x7fee5775d9b0
id of usb: 0x7fee562800e8
id of usb.util: 0x7fee562247c8
id of usb.util.dispose_resources: 0x7fee561ad048
in Main
id of usbtmc.usb: 0x7fee562800e8
id of usbtmc.usb.util: 0x7fee562247c8
id of usbtmc.usb.util.dispose_resources: 0x7fee561ad048
calling Exit()
usbtmc.Instrument.__del__() called for 0x7fee5775d9b0
id of usb: 0x7fee562800e8
id of usb.util: 0x7fee562247c8
id of usb.util.dispose_resources: 0x7fee561ad048
end of usbtmc.Instrument.__del__()
=============================================== =======
usbtmc.Instrument created 0x7fec34b829b0
id of usb: 0x7fec336c3278
id of usb.util: 0x7fec335dbb88
id of usb.util.dispose_resources: 0x7fec335e5048
in Main
id of usbtmc.usb: 0x7fec336c3278
id of usbtmc.usb.util: 0x7fec335dbb88
id of usbtmc.usb.util.dispose_resources: 0x7fec335e5048
calling Exit()
usbtmc.Instrument.__del__() called for 0x7fec34b829b0
id of usb: 0xa40060
Exception ignored in: <bound method Instrument.__del__ of <usbtmc.Instrument object at 0x7fec34b829b0>>
Traceback (most recent call last):
File "/home/don/Electronics/Projects/HF_Meas/Scope_SA/Bug_usb_close/usbtmc.py", line 27, in __del__
AttributeError: 'NoneType' object has no attribute 'util'
=============================================== =======
usbtmc.Instrument created 0x7ff75968c9b0
id of usb: 0x7ff7581af0e8
id of usb.util: 0x7ff7581537c8
id of usb.util.dispose_resources: 0x7ff7580dc048
in Main
id of usbtmc.usb: 0x7ff7581af0e8
id of usbtmc.usb.util: 0x7ff7581537c8
id of usbtmc.usb.util.dispose_resources: 0x7ff7580dc048
calling Exit()
usbtmc.Instrument.__del__() called for 0x7ff75968c9b0
id of usb: 0x7ff7581af0e8
id of usb.util: 0xa40060
Exception ignored in: <bound method Instrument.__del__ of <usbtmc.Instrument object at 0x7ff75968c9b0>>
Traceback (most recent call last):
File "/home/don/Electronics/Projects/HF_Meas/Scope_SA/Bug_usb_close/usbtmc.py", line 28, in __del__
AttributeError: 'NoneType' object has no attribute 'dispose_resources'
使用python3 3.5.1-3在Mint 18.3系统上运行 和python3-usb 1.0.0~b2-2或pyusb-1.0.2的新git pull
答案 0 :(得分:1)
当Python解释器退出时,运行时正在被拆除,对象删除的顺序不是你可以依赖的。实际上,甚至不能保证在解释器退出时会调用__del__()
方法。
自定义__del__
需要访问的对象(包括其他模块)可能已被删除或设置为None
,这将导致您在此处看到的异常(&# 39; NoneType&#39;对象没有属性...)
这不是真正的内存损坏&#34;,它只是为Instrument
类编写的糟糕代码。应使用__enter__
和__exit__
管理任何必要的设置/拆卸上下文,因为__del__
不适用于此目的。所以,这个问题或多或少是Instrument
中的一个错误。通过利用记录here:
Python保证在删除其他全局变量之前,从其模块中删除名称以单个下划线开头的全局变量;如果不存在对此类全局变量的其他引用,这可能有助于确保在调用
__del__()
方法时导入的模块仍然可用。