Как пройти через потоки Python самостоятельно?(Winpdb) - PullRequest
8 голосов
/ 05 августа 2010

Я пытаюсь отладить Python, используя WinPDB, и у меня есть несколько потоков, использующих многопоточность.Я никогда не могу контролировать потоки по отдельности.Если я прерву выполнение, весь скрипт сломается.Если я переберу исходный код одного потока, все остальные продолжат чередование и продолжат выполнение некоторых из них.Это верно с включенной или выключенной синхронизацией.Разве нет способа пройти через поток по отдельности, оставив остальным точку останова?

Является ли WinPDB неподходящим инструментом для этого?Я просто не знаю, что использовать.Eclipse PyDev практически не работает, потому что сам отладчик, похоже, получает ошибки гонки при запуске нескольких потоков.

Что это за инструмент, который на самом деле надежно отладит многопоточную программу Python?*

Спасибо.

1 Ответ

1 голос
/ 09 августа 2010

У меня была похожая проблема, это не самый идеальный ответ, но я опишу ее для вас, и, возможно, вы сможете решить ее.

Я более или менее написал мини-отладчик. Клиент-сервер Udp и функция, которая не делает ничего, кроме захвата глобальной блокировки, спит 0,1 секунды, а затем освобождает ее. Эта функция была передана каждому потоку. Затем я поместил вызов этой функции между критическими областями, которые я хотел отладить. После запуска программы сервер udp будет прослушивать клиента, и если я наберу «pause», он получит ту же глобальную блокировку, которую использует совместно используемая функция, и не сдаст ее, пока я не наберу «play» на клиенте. Таким образом, вы можете получить довольно жесткую остановку ... в зависимости от приложения.

Надеюсь, это поможет ... Крошечный фрагмент ниже. Мое приложение предназначалось для тестовой платформы, поэтому я добавил указатель функции в конструктор базового класса и использовал его вместо time.sleep ()., Что дало мне легкую отладку. Что вы можете сделать, это передать это каждому потоку и добавить вызовы функции паузы в начале и конце ваших функций, и это позволит вам прерваться и т. Д. Я удалил некоторые из команд, но вы можете видеть, что это может быть сделано настолько обширно, насколько вам нужно.

PAUSE_NOW     = thread.allocate_lock()
def pause(s):
'''
    FUNCTION: testStatus

    DESCRIPTION: function passed to all test objects

    INPUTS: none

    RETURNS: none
'''
    global Pause_NOW
    PAUSE_NOW.acquire()
    time.sleep(s)
    PAUSE_NOW.release()

`

def server():
    '''
        \r\n
        FUNCTION: server

        DESCRIPTION: UDP server that launches a UDP client. The client it
                     starts can issue commands defined in cmdlineop. Most
                     functions return a status, but some are meant to block
                     the main thread as a means of pausing a test, in which case
                     a default response is returned.

        INPUTS: none

        RETURNS: none
    '''
    global EXIT
    global Pause_NOW

    host = "localhost"
    port = 21567
    buf  = 1024
    addr = (host,port)

    UDPSock = socket(AF_INET,SOCK_DGRAM)
    UDPSock.bind(addr)
    sleep(1)
    os.startfile('client.py')
    #os.system('start python client.py')
    cmdlineop   =   {
                    'pausenow' : "PAUSE_NOW.acquire()",
                    'playnow'  : "PAUSE_NOW.release()",
                }
    while 1:
        output = 'RECEIVED CMD'
        # if EXIT: break
        data,addr = UDPSock.recvfrom(buf)
        if not data:
            break
        else:
            if cmdlineop.has_key(data.split()[0]):
                exec(cmdlineop[(data.split()[0])])
                UDPSock.sendto(('\n'+output+'\n'),addr)
                data = ''
            else:
                UDPSock.sendto('INVALID CMD',addr)
    UDPSock.close()
...