简体   繁体   English

在 Python 3 中完成线程中的所有任务后,有没有办法返回主菜单循环?

[英]Is there a way to return back to a main menu loop after all tasks in a thread are completed in Python 3?

I'm making a small program that can do some small tasks for me with multiple threads.我正在制作一个小程序,可以用多个线程为我完成一些小任务。 Currently, I have a small menu loop that asks me what task I want to run, it then asks me for the information it needs to complete the task, and sets up a specified number of threads to complete the task through a queue.目前,我有一个小菜单循环,询问我要运行什么任务,然后询问我完成任务所需的信息,并设置指定数量的线程以通过队列完成任务。

Currently, my menu loop code looks like this and is run when the program starts:目前,我的菜单循环代码如下所示,并在程序启动时运行:

# menu loop
def menu_loop():
    while True:
        choice = menu()
        if choice is not None:
            break
    # configure program
    if choice == 1:
        while True:
            config_choice = configure() # another menu loop
            if config_choice is not None:
                if config_choice == 0:
                    clear_screen()
                    print(f"[*] {red}exiting config...\n")
                    menu_loop()
                elif config_choice == 1:
                    num_of_threads = int(input("number of threads: "))
                    clear_screen()
                    print(f"[*] {green}number of threads set to {num_of_threads}.\n")
                    menu_loop()
                elif config_choice == 2:
                    folder_path = input("folder path for results: ")
                    clear_screen()
                    print(f"[*] {green}path to results set to {folder_path}.\n")
                    menu_loop()
                break

    if choice == 2:
        strings = [line.strip() for line in open((input("path to string file: ")), "r")] # load strings
        for string in strings:
            q.put(string) # insert each string into queue
        print(f"{green}loaded {len(strings)} strings into the checker.") # log
        with open(string_results_ml, "a+") as sr_multi_line:
            sr_multi_line.write("------------------------------\n") # first line of the file
        for i in range(int(input("number of threads: "))):
            Thread(target=check_string, args=(q,)).start() # start threads

The code for the check_string function is as follows: check_string function 的代码如下:

def check_string(q):
    while True:
        try:
            work = q.get()
            if q.empty(): # needed because except doesn't trigger half the time
                sleep(1)
                quit()
        except queue.Empty:
            quit()
        headers = {"Content-Type": "application/json"}
        url = "https://[redacted]/{}".format(work)
        try:
            r = requests.get(url, headers=headers)
            jd = r.json()
            if r.status_code == 200:
                try:
                    result = jd["result"]
                    # write working strings and their data to the results file
                    with open(string_results, "a+") as s_r:
                        s_r.write(f"{string} - {result}\n")
                    with lock:
                        print(f"[{blue}{r.status_code}{rs}]{green} got result for {string}")
                    sleep(0.3) # sleep for a bit, time out
                except:
                    print(f"[{blue}{r.status_code}{rs}]{red} something happened while parsing the data.")
            else:
                with lock:
                    print(f"[{blue}{r.status_code}{rs}]{red} no results for {string}")
        except:
            with lock:
                print(f"{red}fatal error while checking {string}! the string has been written to a separate file for you to check later.")
            with open(fatal, "a+") as f_e:
                f_e.write(string + "\n")
        q.task_done()

Right now, what happens after all the strings are done being checked is that the program just hangs and doesn't go back to the menu loop.现在,在检查完所有字符串后发生的情况是程序只是挂起并且没有 go 回到菜单循环。 There is no code for it to go back to the loop currently but it should at least quit after all strings are done being checked.目前没有代码可以将 go 返回到循环,但它至少应该在检查完所有字符串后退出。 It just hangs currently.它目前只是挂起。 When I press CTRL-C, it gives me the following exception:当我按 CTRL-C 时,它给了我以下异常:

^CException ignored in: <module 'threading' from '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1307, in _shutdown
    lock.acquire()
KeyboardInterrupt

How can I make the program go back to the main menu loop after all strings are done being checked instead of just hanging?在检查完所有字符串而不是挂起之后,如何使程序 go 回到主菜单循环?

Your threads are stopping because the queue is empty and they are waiting for new item to be queued.您的线程正在停止,因为队列为空并且它们正在等待新项目排队。 By default, queue.get() blocks if the queue is empty.默认情况下,如果队列为空,则queue.get()会阻塞。 In your code, check the queue before q.get() .在您的代码中,检查q.get()之前的队列。 In addition, change q.get() to q.get(false) to prevent blocking (an error will be thrown if empty queue).另外,将q.get()更改为q.get(false)以防止阻塞(如果为空队列将抛出错误)。

while True:
    try:
        if q.empty(): quit()  # exit thread if no items left - add this line
        work = q.get(false) # don't block to be safe - update this line
        if q.empty(): # needed because except doesn't trigger half the time
            time.sleep(1)
            quit()
    except queue.Empty:
        quit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM