2013-04-04 9 views
2

Я пытаюсь отлаживать приложение, которое использует библиотеку pynetdicom. Я не уверен, насколько уместна эта конкретная деталь, однако, что имеет значение, это то, что она сильно использует многопоточность для запуска задач прослушивания фоновых сокетов без блокировки основного потока. Для воспроизведения этого примера можно использовать пример storescp.py.pydev multithread debugging

Всякий раз, когда я устанавливаю точку останова, которая получает встречается (независимо от того, какой поток, основной или ребенка, он получает встречается в), я получаю следующее отслеживающий:

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 monkey-patches __pydevd_id__ в порожденные потоки, однако не удается их исправить в этих потоках, потому что они являются, по сути, подклассами, а не прямыми экземплярами threading.Thread (в этом случае рабочий является экземпляром class Association(threading.Thread):).

Конечно, я не знаю PyDev достаточно хорошо, чтобы подтвердить эту теорию, или исправить ее. И, похоже, не интернет.

Подклассификация Thread настолько редко используется шаблон, который просто не учитывается в архитектуре PyDev? Не переделывая библиотеку, как можно устранить эту проблему?

ответ

2

Мне просто нужно было усерднее смотреть на эту трассу.

Библиотека pynetdicom в своем подклассе threading.Thread, overrode __getattr__ и несколько сломала его. Проблема была в следующем:

def __getattr__(self, attr): 
    #while not self.AssociationEstablished: 
    # time.sleep(0.001) 
    obj = eval(attr) 

    # do some stuff 

    return obj 

Когда несуществующий атрибут передан, возникает NameError. Это не захватывается monkeypatching рутина Pydev в (if thread.__pydevd_id__ raises AttributeError, thread.__pydevd_id__ = stuff)

Решение было обновить этот раздел Thusly:

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__ следует, если запрашиваемый атрибут Безразлично не существует.