Потоки Python и PySimpleGUI

--ПЕРЕСМОТРЕНО РЕШЕНИЕМ ОТ MikeyB--

Спасибо Майки за указание на простое решение. Я чувствую, что иногда слишком много размышлений вкладывается в решение, и это простое решение, которое решает проблему.

Я добавил небольшую функцию, которая просматривает мои каталоги, которые я хочу отслеживать, и устанавливает для переменной значение True или False.

def file_check(working_pdf):
    if len(gb1(working_pdf, '*.pdf')) == 0:
        pdf_available = False

    if len(gb1(working_pdf, '*.pdf')) > 0:
        pdf_available = True

    return pdf_available

Затем это вызывается в цикле событий PySimpleGUI.

    if files_available is True:
        for client in client_running_list:
            working_pdf, ext = folder_Func(client)
            pdf_available = file_check(working_pdf)
            if pdf_available is True:
                analyzer_queue.put(client)
                for x in range(10):
                    t = Thread(target=analyzer)
                    t.daemon = True
                    t.start()

--Оригинальный пост--

У меня есть программа, которая просматривает каталоги, определенные с помощью функции, и если есть файлы, она анализирует эти файлы, а затем перемещает данные в базу данных. Если при запуске программы в каталогах есть файлы, она работает по назначению, но при добавлении нового файла функция не выполняется. Кажется, что бесконечный цикл не выполняется через каталог.

У меня есть пользовательский интерфейс через PySimpleGUI, в котором используется цикл while True:, поэтому мне приходится отключать функцию через поток. Я использую очередь и пытаюсь определить, где мне нужен цикл «while True:», чтобы постоянно искать в папке новые файлы.

Ниже приведена часть кода (отступы ниже неправильные):

def analyzer():
while True:
    client = analyzer_queue.get()
    working_pdf, archive_path_datetime = folder_Func(client)
    while True:
        if len(gb1(working_pdf, '*.pdf')) == 0:
            break
        else:
            print(f'Found files in ', client, ' folder. Starting Parse.')
            ##########################################################
            # Start Parse of PDF's
            # Calls pdf parse function.
            # Arguments are Client Number, and PDF to parse.
            # Returns DF of items to insert into SQL Database
            ##########################################################
            ch(working_pdf)
            for pdf in gb1(working_pdf, "*.pdf"):
                items_found_df = pdf_parse(client, pdf)


            ##########################################################
            # Connect to SQL Server and insert items
            # Calls database connection function.
            ##########################################################
                azureDBengine = sqlalchemyConn()
                items_found_df.to_sql("MainData_Capture",azureDBengine,if_exists='append',method='multi',index=False)


            ##########################################################
            # Move file to Archive
            ##########################################################
                if not ospath.exists(archive_path_datetime):
                    osmakedirs(archive_path_datetime)
                    print("Created Archive Folder.")
                file_move(working_pdf, archive_path_datetime, pdf)
            print('All Files Processed.')
            analyzer_queue.task_done()
while True:
    event_dashboard, values_dashboard = dashboard_form.Read(timeout=1000)
    if dashboard_form is None or event_dashboard == 'Exit':
        dashboard_form.Close()
        break

    for client in active_client_list:
        client_start_button_action(client, event_dashboard, dashboard_form)
        client_stop_button_action(client, event_dashboard, dashboard_form)

    if event_dashboard == 'Start Analyze':
        dashboard_form.FindElement(f'Start Analyze').Update(disabled=True)
        dashboard_form.FindElement(f'Stop Analyze').Update(disabled=False)
        print('Analyzer Started')

        for client in client_running_list:
            analyzer_queue.put(client)
        for x in range(10):
            t = Thread(target=analyzer)
            t.daemon = True
            t.start()

    if event_dashboard == 'Stop Analyze':
        dashboard_form.FindElement(f'Stop Analyze').Update(disabled=True)
        dashboard_form.FindElement(f'Start Analyze').Update(disabled=False)
        print('Analyzer Stopped')
        analyzer_queue.empty()

person Adam    schedule 17.03.2020    source источник
comment
Вот и все! Хорошая работа, чтобы понять это. Вы можете делать много полезных вещей в цикле событий, включая запуск потоков, которые будут выполнять длинные задачи, или проверку глобальных переменных, которые устанавливают потоки, или проверку очереди, или опроса оборудования, или ______. Как только вы напишете больше кода PySimpleGUI, обратите внимание на новые соглашения о кодировании. Вам понравится компактность. Вы можете сократить такие вещи, как dashboard_form [f'Stop Analyze ']. Update (disabled = True). Нет необходимости вызывать FindElement. О, еще один совет ... вы можете установить daemon = True при создании потока. Это параметр для Thread.   -  person Mike from PSG    schedule 18.03.2020
comment
Спасибо за советы. Где новые соглашения о кодировании? Гитхаб PySimpleGUI?   -  person Adam    schedule 18.03.2020
comment
Да, примеры в документации и демонстрационные программы были обновлены для использования новейших соглашений о кодировании.   -  person Mike from PSG    schedule 19.03.2020


Ответы (1)


Вы можете искать что-то новое, опрашивать оборудование, выполнять любые «проверки», которые не занимают много времени, в цикле событий PySimpleGUI в вашем коде.

Добавив тайм-аут к вашему вызову чтения, ваш цикл событий будет запускаться периодически. Используйте это для периодической проверки ваших новых файлов. Это также тот же метод, который можно использовать для проверки входящих сообщений из потоков с использованием очереди.

while True:             # Event Loop
    event, values = window.read(timeout=500)        # returns every 500 ms
    if event in (None, 'Exit'):
        break
    if check_for_changes():
        do_something()       

Вы запускаете свой каждую секунду. Это должно подойти для опроса новых файлов. Добавьте цикл while в цикл событий. Если он слишком длинный, развернитесь как поток, как вы сказали, и замените check_for_changes на check_for_message_from_threads.

person Mike from PSG    schedule 18.03.2020