Проблема синхронизации Python при вызове функции в другом

#python #function #tkinter #timing

Вопрос:

У меня есть код ниже :

 def update_contact_from_crm_to_import_in_365():

sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
search_result = my_cursor.execute(sql)
search_result = my_cursor.fetchall()
sql_result.clear()
sql_result.append(search_result)

Filter(sql_result[0])

# Get id of sql result to pass them
list_get_selected_id.clear()
for res in (sql_result):
    for id in (res):
        list_get_selected_id.append(id[0])


time.sleep(5)

validate1 = messagebox.askquestion("Update ?", "Launch update ?")
if validate1 == 'yes':
    open_dynamics_365_full_contact_list()
 

Моя проблема в том, что Filter(sql_result[0]) , кажется, начинается в самом конце update_contact_from_crm_to_import_in_365 функции (после messagebox )

До сих пор, когда я звоню update_contact_from_crm_to_import_in_365() , он отображает окно сообщений, и как только на него отвечают, он звонит Filter() .

Но я хотел бы позвонить Filter , подождать 5 секунд, пока фильтр продолжится и закончится, а затем отобразить окно сообщений.

Как мне это сделать, пожалуйста ?

Я читал о потоковой передаче, но я всего лишь новичок в Python, поэтому мне пока немного сложно понять это.

Заранее спасибо

Комментарии:

1. что делает фильтр? Можете ли вы опубликовать его код в ОП?

2. если это tkinter так, то вы можете использовать root.after(5000, function_name) функцию для запуска через 5000 мс (5 секунд). И function_name означает имя функции без () (так называемой callback )

3. у вас неправильные отступы, поэтому мы не можем сказать, как работает этот код. Отредактируйте вопрос, снова введите код, выберите код и используйте Ctrl K для правильного форматирования кода.

4. @tstoev : Filter() фактически использует результат SQL-запроса для подачи виджета (т. к. treeview). До сих пор все работает нормально, но просмотр дерева обновляется только после ответа на сообщение. Это похоже на то, как если бы окно сообщений останавливало выполнение кода в фоновом режиме. Но поскольку вызов Filter() находится перед ящиком сообщений, я не понимаю, почему …

5. @furas: Спасибо за ваш ответ, но я пытаюсь сделать обратное, я не хочу откладывать вызов фильтра (), пытался дать ему некоторое время для продолжения, но всплывающее окно окна сообщений появляется почти мгновенно, когда я вызываю update_contact_from_crm_to_import_in_365.

Ответ №1:

Я не могу запустить его, но проблема может заключаться в том, что mainloop сначала запускается функция update_contact_from_crm_to_import_in_365 , и она ждет ее окончания, а затем обновляет виджеты в widow. Таким образом, он может обновить все виджеты за один момент, чтобы окно меньше мерцало.

В вашей ситуации у вас может быть два решения

  1. Вы можете использовать root.after(5000, function_with_message) вместо sleep() , а затем update_contact_from_crm_to_import_in_365 завершите работу, и он вернется к mainloop тому, что обновит виджеты — и через 5000 мс он запустится function_with_message .
     def show_message():
        validate1 = messagebox.askquestion("Update ?", "Launch update ?")
        if validate1 == 'yes':
            open_dynamics_365_full_contact_list()
    
    def update_contact_from_crm_to_import_in_365():
    
        sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
        search_result = my_cursor.execute(sql)
        search_result = my_cursor.fetchall()
        sql_result.clear()
        sql_result.append(search_result)
    
        Filter(sql_result[0])
    
        # Get id of sql result to pass them
        list_get_selected_id.clear()
        for res in (sql_result):
            for id in (res):
                list_get_selected_id.append(id[0])
    
        root.after(5000, show_message)
        #root.after(1, show_message) # it will no need to wait so long.
     
  2. Вы можете использовать root.update() after Filter() для принудительного mainloop обновления виджетов до завершения функции.
     def update_contact_from_crm_to_import_in_365():
    
        sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
        search_result = my_cursor.execute(sql)
        search_result = my_cursor.fetchall()
        sql_result.clear()
        sql_result.append(search_result)
    
        Filter(sql_result[0])
    
        # Get id of sql result to pass them
        list_get_selected_id.clear()
        for res in (sql_result):
            for id in (res):
                list_get_selected_id.append(id[0])
    
        root.update()  # force tkinter to update widgets in window
        #time.sleep(5)
    
        validate1 = messagebox.askquestion("Update ?", "Launch update ?")
        if validate1 == 'yes':
            open_dynamics_365_full_contact_list()
     

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