Python多处理意外阻塞

时间:2014-05-13 18:05:22

标签: python multithreading multiprocessing blocking

我在Linux环境中使用apache和modpython运行python脚本。它集成在一个允许文件处理的Web工具中。我的脚本中包含文件处理的部分可能会有很长的执行时间。在我的代码的原始版本中,脚本等待处理文件,最后它返回一些带有链接的html以下载生成的文件。

submit.html

<html>
    <body>
        <form enctype="multipart/form-data" action="./my_script.py/main" method="post">
            <div> <input type="file" name="file"> </div>
            <div> <input type="submit" value="Upload"> </div>
    </body>
</html>

my_script.py

def main(file):
    process(file)
    return "<p> Download your file <a href='./%s'></a>", % file

def process(file)
    #some file treatment here, and a resulting file is stored in current directory

我想写一个允许用户通过电子邮件接收结果文件的功能。在那种情况下,一旦他上传了他的文件,我想将他重定向到一个页面,他可以继续使用网络工具,而他的文件正在服务器端处理,因此用户不是Unix分叉。我已经使用这3个选项进行了多次测试,但我总是被运行脚本阻止。根据我的理解,多处理最适合我的情况,所以我试过这个:

my_script.py

def main(file, receiver_mail_address):
    p = Process(target=process_and_email, args=(file, receiver_mail_address)
    p.start()
    return "<p> The resulting files will be emailed to you at %s.</p>" % receiver_mail_address

def process_and_email(file, receiver_mail_address):
    #some file processing here, and emailing. these functions work perfectly as expected.

在这种情况下,我跳过了p.join()步骤,这在python docs中说到了

  

&#34;阻止调用线程,直到其join()方法为的进程   调用终止或直到可选超时发生。&#34;

但在我的情况下,它仍然被阻止。这意味着我必须等到我的进程p在到达return语句之前结束。我怎么能这样做?


编辑:

我尝试更改为subprocess模块。所以我将process_and_email函数放入一个名为process_and_email.py的新文件中,并修改了主脚本:

my_script.py

def main(file, receiver_mail_address):
    directory = os.path.firname(__file__)
    path = os.path.join(directory, 'process_and_email.py')

    subprocess.Popen(['python2.7', path, file, receiver_mail_address], shell=True)

    return "<p> The resulting files will be emailed to you at %s.</p>" % receiver_mail_address

我仍然遇到同样的问题:在process_and_email.py文件完全执行之前,我无法访问return语句。

2 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为在所有非守护进程子进程完成他们正在进行的工作之前,您的父进程不会退出。因此,在您的情况下,process_and_email需要在脚本退出之前完成,即使main已完成。您可以使子进程成为守护进程,这将允许父脚本立即退出,但它会在退出之前终止工作进程,这也不是您想要的。

我认为更好的选择是使用subprocess模块生成一个单独的Python脚本来在后台进行处理。这样您的父脚本就可以退出,并使工作进程保持运行。

答案 1 :(得分:1)

Web应用程序中使用的常见模式是维护一个全局队列,例如beanstalkd,它具有一个名为beanstalkc的漂亮Python接口。然后,您可以将这些作业提交到队列,并拥有一个单独的程序/进程监视,可以对队列中的项进行排队和处理。