Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-正在终止未正确引用SIGINT-global变量的线程_Python_Multithreading_Sigint - Fatal编程技术网

Python-正在终止未正确引用SIGINT-global变量的线程

Python-正在终止未正确引用SIGINT-global变量的线程,python,multithreading,sigint,Python,Multithreading,Sigint,我正在努力使我的线程可以捕捉到一个信号。在我看来,kill_received singleton list与signal_handler和do_uploads在同一个名称空间中,并且引用了同一个内存位置。但当我在C运行时控制它时,我看到从print kill_received[0]打印False,而这应该是真的,因为我点击了control-C kill_received = [False] def signal_handler(signal, frame): global kill_r

我正在努力使我的线程可以捕捉到一个信号。在我看来,kill_received singleton list与signal_handler和do_uploads在同一个名称空间中,并且引用了同一个内存位置。但当我在C运行时控制它时,我看到从print kill_received[0]打印False,而这应该是真的,因为我点击了control-C

kill_received = [False]

def signal_handler(signal, frame):
    global kill_received
    kill_received[0] = True
    print "\nYou pressed Ctrl+C!"
    print (
        "Your logs and their locations are:"
        "\n{}\n{}\n{}".format(debug, error, info))
    sys.exit(0)

def do_the_uploads(file_list, file_quantity,
        retry_list, authenticate):
    """The uploading engine"""
    value = raw_input(
        "\nPlease enter how many conncurent "
        "uploads you want at one time(example: 200)> ")
    value = int(value)
    logger.info('{} conncurent uploads will be used.'.format(value))

    confirm = raw_input(
        "\nProceed to upload files? Enter [Y/y] for yes: ").upper()
    if confirm == "Y":
        kill_received = False
        sys.stdout.write("\x1b[2J\x1b[H")
        q = Queue.Queue()

        def worker():
            global kill_received
            while True and not kill_received[0]:
                print kill_received[0]
                item = q.get()
                upload_file(item, file_quantity, retry_list, authenticate)
                q.task_done()

        for i in range(value):
            t = Thread(target=worker)
            t.setDaemon(True)
            t.start()

        for item in file_list:
            q.put(item)

        q.join()
        print "Finished. Cleaning up processes...",
        #Allowing the threads to cleanup
        time.sleep(4)
        print "done."
从主脚本:

from modules.upload_actions import do_the_uploads, retry, signal_handler

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)

    retry_list = []
    file_list, authenticate, ticket_number = main()
    file_quantity = FileQuantity(len(file_list))
    do_the_uploads(file_list, file_quantity, 
            retry_list, authenticate)
更新:

仍然没有成功,但我更改了语法,因为它更干净:

   def worker():
        global kill_received
        while not kill_received[0]:
            time.sleep(1)
            print kill_received[0]
            item = q.get()
            upload_file(item, file_quantity, retry_list, authenticate)
            q.task_done()

你看到虚假打印的原因是因为它从来没有机会打印它。您在每次点击打印kill_收到[0]语句之前将其杀死

想想看。在执行以下语句之间,很可能会按Ctrl-C键:

while True and not kill_received[0]:
print kill_received[0]
本声明:

while True and not kill_received[0]:
print kill_received[0]
但这是不可能的。在任何其他时间中断任何线程都会导致它们停止while语句中的循环,并且永远不会打印任何内容


编辑:您有一行:kill_received=False,这可能会导致您出现问题。它可能应该是kill_received[0]=False

您看到False打印的原因是因为它从来没有机会打印它。您在每次点击打印kill_收到[0]语句之前将其杀死

想想看。在执行以下语句之间,很可能会按Ctrl-C键:

while True and not kill_received[0]:
print kill_received[0]
本声明:

while True and not kill_received[0]:
print kill_received[0]
但这是不可能的。在任何其他时间中断任何线程都会导致它们停止while语句中的循环,并且永远不会打印任何内容


编辑:您有一行:kill_received=False,这可能会导致您出现问题。可能应该是kill_received[0]=False

了解发生了什么的关键是你所做的评论


不。当所有线程都完成时,我会…但不是在线程执行期间,它们必须上载所有文件

这一行代码:

q.join()
与您可能期望的相反,control-C不会导致它停止等待队列-直到此调用返回后,它才会接受control-C。因此,发生的情况是,您的所有线程都完成了任务并清空了队列,然后正在排队等待

item = q.get()
只有在最后一个线程调用q.task_done之后,主线程才会返回,然后处理control-C。然而,在这一点上,所有线程都被困在队列中等待更多它们无法获得的项目,因此它们永远不会退出循环

这里可能会发生比这更多的事情,但要确定这是否是问题所在,请尝试在繁忙的等待中等待队列为空:

while not q.empty():
    time.sleep(0.1)
q.join()
之后需要加入,因为队列为空意味着最后一次上载已从队列中拉出来,而不是它已完成

您还可以向队列中添加一个项目,表示线程应该完成,例如None。比如说,

    def worker():
        global kill_received
        while True and not kill_received[0]:
            print kill_received[0]
            item = q.get()
            if item is None:
                q.task_done()
                break
            upload_file(item, file_quantity, retry_list, authenticate)
            q.task_done()

    for i in range(value):
        t = Thread(target=worker)
        t.setDaemon(True)
        t.start()

    for item in file_list:
        q.put(item)

    for i in range(value):
        q.put(None)
当然,这假定None不是要上载的有效值。这对control-C问题没有帮助,但您可能会发现,确保程序正常完成时线程退出是有帮助的


作为一般帮助,当您使用线程进行测试时,有一种方法可以打印出所有线程的堆栈跟踪可能会很有帮助。谈论如何做到这一点。

了解发生了什么的关键是你所做的评论


不。当所有线程都完成时,我会…但不是在线程执行期间,它们必须上载所有文件

这一行代码:

q.join()
与您可能期望的相反,control-C不会导致它停止等待队列-直到此调用返回后,它才会接受control-C。因此,发生的情况是,您的所有线程都完成了任务并清空了队列,然后正在排队等待

item = q.get()
只有在最后一个线程调用q.task_done之后,主线程才会返回,然后处理control-C。然而,在这一点上,所有线程都被困在队列中等待更多它们无法获得的项目,因此它们永远不会退出循环

这里可能会发生比这更多的事情,但要确定这是否是问题所在,请尝试在繁忙的等待中等待队列为空:

while not q.empty():
    time.sleep(0.1)
q.join()
之后需要加入,因为队列为空意味着最后一次上载已从队列中拉出来,而不是它已完成

您还可以向队列中添加一个项目,表示线程应该完成,例如None。比如说,

    def worker():
        global kill_received
        while True and not kill_received[0]:
            print kill_received[0]
            item = q.get()
            if item is None:
                q.task_done()
                break
            upload_file(item, file_quantity, retry_list, authenticate)
            q.task_done()

    for i in range(value):
        t = Thread(target=worker)
        t.setDaemon(True)
        t.start()

    for item in file_list:
        q.put(item)

    for i in range(value):
        q.put(None)
当然,这假定None不是要上载的有效值。这对control-C问题没有帮助,但您可能会发现,确保程序正常完成时线程退出是有帮助的

作为一般帮助,当您使用线程进行测试时,有一种方法可以打印出所有线程的堆栈跟踪可能会很有帮助。谈论如何做到这一点
.

您是否曾看到您按Ctrl+C!?不。当所有线程都已完成时,我会…但不是在线程执行期间,它们必须上载所有文件。您是否已将kill_received=False行修复为kill_received[0]=False,然后重试?您是否曾看到您按Ctrl+C!的消息!?否。当所有线程都完成时,我会…但不是在线程执行期间,它们必须上载所有文件。是否已修复kill_received=False行以kill_received[0]=False,然后重试?否,线程正在继续,并在循环继续时打印False。while True和not kill_received仍为True,因此线程将继续。@是否可以尝试在while循环后添加行打印检查:%s“%kill_received[0],以查看它们是否正在退出loop@Rob,试过这个。我把它放在while循环之后,但是它从来没有运行过,所以循环永远不会退出。不,线程正在继续,并且随着循环的继续打印False。while True和not kill_received仍为True,因此线程将继续。@是否可以尝试在while循环后添加行打印检查:%s“%kill_received[0],以查看它们是否正在退出loop@Rob,试过这个。我把它放在while循环之后,但是它从来没有运行过,所以循环从来没有退出过。呃……经过多次不同的尝试,在这方面没有获胜的机会。如果收到信号,是否有办法释放q.join?@dman使用time.sleep循环无效?如果您有足够的线程/足够少的作业,那么队列将很快清空。您是否尝试过只使用一个或两个工作线程来处理相当多的作业?您也可以尝试使用while q.unfinishedtasks:作为循环条件。呃……在多次不同的尝试之后,在这方面没有赢家。如果收到信号,是否有办法释放q.join?@dman使用time.sleep循环无效?如果您有足够的线程/足够少的作业,那么队列将很快清空。您是否尝试过只使用一个或两个工作线程来处理相当多的作业?您还可以尝试使用whileq.unfinishedtasks:作为循环条件。