我正在尝试调试使用pynetdicom库的应用程序。我不确定具体细节是多么相关,但是相关的是它大量使用多线程来运行后台套接字监听器任务而不阻塞主线程。 storescp.py示例可用于重现此内容。
每当我放置一个遇到的断点(无论遇到什么线程,主要或子进程),我都会得到以下回溯:
Traceback (most recent call last):
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd.py", line 1397, in <module>
debugger.run(setup['file'], None, None)
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd.py", line 1090, in run
pydev_imports.execfile(file, globals, locals) #execute the script
File "/Users/alexw/Development/Python/kreport2/KReport2/dicomdatascraper.py", line 183, in <module>
oldDicomList = copy.copy(newData)
File "/Users/alexw/Development/Python/kreport2/KReport2/dicomdatascraper.py", line 183, in <module>
oldDicomList = copy.copy(newData)
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd_frame.py", line 135, in trace_dispatch
self.doWaitSuspend(thread, frame, event, arg)
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd_frame.py", line 25, in doWaitSuspend
self._args[0].doWaitSuspend(*args, **kwargs)
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd.py", line 832, in doWaitSuspend
self.processInternalCommands()
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd.py", line 360, in processInternalCommands
thread_id = GetThreadId(t)
File "/Applications/Aptana Studio 3/plugins/org.python.pydev_2.7.0.2013012902/pysrc/pydevd_constants.py", line 140, in GetThreadId
return thread.__pydevd_id__
File "/Users/alexw/.virtualenvs/kreport2dev/devlibs/pynetdicom/source/netdicom/applicationentity.py", line 73, in __getattr__
obj = eval(attr)()
File "<string>", line 1, in <module>
NameError: name '__pydevd_id__' is not defined
我的想法是,或许,为了使事情有效,PyDev会将__pydevd_id__
修补为生成的线程,但无法将这些线程修补到这些线程,因为它们是,实际上,子类而不是threading.Thread
的直接实例(在这种情况下,worker是class Association(threading.Thread):
的实例)。
当然,我不太了解PyDev以证实这个理论,或者解决它。互联网似乎也没有。
子类化Thread
是否很少使用在PyDev架构中根本不考虑的模式?如果不重新设计库,那么如何解决这个问题呢?
答案 0 :(得分:2)
我只需要更加努力地回顾那个追溯。
pynetdicom库在其threading.Thread
的子类中,覆盖__getattr__
并且有点破坏了它。问题是:
def __getattr__(self, attr):
#while not self.AssociationEstablished:
# time.sleep(0.001)
obj = eval(attr)
# do some stuff
return obj
当传递不存在的属性时,会引发NameError。这不是由pydev的monkeypatching例程(if thread.__pydevd_id__ raises AttributeError, thread.__pydevd_id__ = stuff
)
解决方案是如此更新该部分:
def __getattr__(self, attr):
#while not self.AssociationEstablished:
# time.sleep(0.001)
try:
obj = eval(attr)
except NameError:
raise AttributeError
# do some stuff
return obj
这会拦截NameError并引发AttributeError,如果查询的属性不存在则应该__getattr__
。