【问题标题】:How do I cleanly exit from a multiprocessing script?如何干净地退出多处理脚本?
【发布时间】:2013-03-27 07:32:14
【问题描述】:

我正在为我的网站构建一个非阻塞聊天应用程序,我决定实现一些多处理来处理数据库查询和实时消息传递。

我假设当用户登陆给定 URL 以查看他们与其他人的对话时,我将启动脚本,开始多处理,消息将被添加到队列并显示在页面上,新消息将被发送到与数据库等交互的单独队列中。(随之而来的是常规消息功能。)

但是,当用户离开此页面时会发生什么?我假设我需要退出这些不同的进程,但目前,这并不适合“干净”的退出。我将不得不终止进程并根据多处理文档:

Warning: If this method (terminate()) is used when the associated process is using a pipe 
or queue then the pipe or queue is liable to become corrupted and may become 
unusable by other process.Similarly, if the process has acquired a lock or 
semaphore etc. then terminating it is liable to cause other processes to 
deadlock.

我也调查过sys.exit();但是,如果在各种进程中不使用terminate(),它不会完全退出脚本。

这是我为解决此问题而简化的代码。如果我需要改变它,那完全没问题。我只是想确保我正确地处理这件事。

import multiprocessing
import Queue
import time
import sys

## Get all past messages
def batch_messages():   

    # The messages list here will be attained via a db query
    messages = [">> This is the message.", ">> Hello, how are you doing today?", ">> Really good!"]
    for m in messages:
        print m

## Add messages to the DB   
def add_messages(q2):   

    while True:
        # Retrieve from the queue
        message_to_db = q2.get()

        # For testing purposes only; perfrom another DB query to add the message to the DB
        print message_to_db, "(Add to DB)"

## Recieve new, inputted messages.
def receive_new_message(q1, q2):

    while True:
        # Add the new message to the queue:
        new_message = q1.get()

        # Print the message to the (other user's) screen
        print ">>", new_message

        # Add the q1 message to q2 for databse manipulation
        q2.put(new_message)

def shutdown():
    print "Shutdown initiated"
    p_rec.terminate()
    p_batch.terminate()
    p_add.terminate()
    sys.exit()

if __name__ == "__main__":

    # Set up the queue
    q1 = multiprocessing.Queue()
    q2 = multiprocessing.Queue()

    # Set up the processes
    p_batch = multiprocessing.Process(target=batch_messages)
    p_add = multiprocessing.Process(target=add_messages, args=(q2,))
    p_rec = multiprocessing.Process(target=receive_new_message, args=(q1, q2,))

    # Start the processes   
    p_batch.start() # Perfrom batch get 
    p_rec.start()
    p_add.start()

    time.sleep(0.1) # Test: Sleep to allow proper formatting

    while True:

        # Enter a new message
        input_message = raw_input("Type a message: ")

        # TEST PURPOSES ONLY: shutdown
        if input_message == "shutdown_now":
            shutdown()

        # Add the new message to the queue:
        q1.put(input_message)

        # Let the processes catch up before printing "Type a message: " again. (Shell purposes only)
        time.sleep(0.1)

我应该如何处理这种情况?我的代码是否需要从根本上修改?如果需要,我应该如何修复它?

感谢任何想法、cmets、修订或资源。

谢谢!

【问题讨论】:

  • 注:您不需要在标题前加上“python –”,这就是 StackOverflow 的标签的用途。
  • 有效点,现已修复。
  • 那么你为什么不能做一个干净的退出呢?在关闭时向每个子进程传递消息,它应该停止做它正在做的任何事情并退出。为此,您可能需要一个单独的线程(在每个子进程上)。
  • 哦,顺便说一句:你不能用线程代替进程吗?它更安全,更易于维护。
  • 终止有什么问题?我想它应该可以正常工作。

标签: python real-time multiprocessing nonblocking


【解决方案1】:

免责声明:我实际上并不了解 python。但多线程概念在我所知道的所有语言中都足够相似,因此我有足够的信心尝试回答。

当使用多个线程/进程时,每个线程/进程都应该在循环中包含一个步骤来检查变量,(我经常将变量称为“active”或“keepGoing”之类的东西,它通常是一个布尔值。)

该变量通常在线程之间共享,或者作为消息发送到每个线程,具体取决于您的编程语言以及您希望何时停止处理,(先完成您的工作是/否?)

一旦设置了变量,所有线程都会退出它们的处理循环并继续退出它们的线程。

在您的情况下,您有一个“while true”循环。这永远不会退出。将其更改为在设置变量时退出,并且在到达函数退出时线程应自行关闭。

【讨论】:

  • 感谢您对此事的意见。我一定会测试出来的。
猜你喜欢
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多