在 Python 中运行后台进程,不要等待
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37058013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Run background process in Python and do NOT wait
提问by harperville
My goal is simple: kick off rsync and DO NOT WAIT.
我的目标很简单:启动 rsync 并且不要等待。
Python 2.7.9 on Debian
Debian 上的 Python 2.7.9
Sample code:
示例代码:
rsync_cmd = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1)
rsync_cmd2 = "/usr/bin/rsync -a -e 'ssh -i /home/myuser/.ssh/id_rsa' {0}@{1}:'{2}' {3} &".format(remote_user, remote_server, file1, file1)
rsync_path = "/usr/bin/rsync"
rsync_args = shlex.split("-a -e 'ssh -i /home/mysuser/.ssh/id_rsa' {0}@{1}:'{2}' {3}".format(remote_user, remote_server, file1, file1))
#subprocess.call(rsync_cmd, shell=True) # This isn't supposed to work but I tried it
#subprocess.Popen(rsync_cmd, shell=True) # This is supposed to be the solution but not for me
#subprocess.Popen(rsync_cmd2, shell=True) # Adding my own shell "&" to background it, still fails
#subprocess.Popen(rsync_cmd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) # This doesn't work
#subprocess.Popen(shlex.split(rsync_cmd)) # This doesn't work
#os.execv(rsync_path, rsync_args) # This doesn't work
#os.spawnv(os.P_NOWAIT, rsync_path, rsync_args) # This doesn't work
#os.system(rsync_cmd2) # This doesn't work
print "DONE"
(I've commented out the execution commands only because I'm actually keeping all of my trials in my code so that I know what I've done and what I haven't done. Obviously, I would run the script with the right line uncommented.)
(我已经注释掉了执行命令,只是因为我实际上将所有试验保留在我的代码中,以便我知道我做了什么和我没有做的事情。显然,我会用正确的方式运行脚本行未注释。)
What happens is this...I can watch the transfer on the server and when it's finished, then I get a "DONE" printed to the screen.
会发生什么......我可以在服务器上观看传输,当它完成时,我会在屏幕上打印一个“完成”。
What I'd like to have happen is a "DONE" printed immediately after issuing the rsync
command and for the transfer to start.
我希望发生的是在发出rsync
命令并开始传输后立即打印的“完成” 。
Seems very straight-forward. I've followed details outlined in other posts, like thisone and thisone, but something is preventing it from working for me.
看起来非常直接。我已经遵循了其他帖子中概述的细节,比如这个和这个,但是有些东西阻止了它对我有用。
Thanks ahead of time.
提前致谢。
(I have tried everything I can find in StackExchange and don't feel like this is a duplicate because I still can't get it to work. Something isn't right in my setup and need help.)
(我已经尝试了我可以在 StackExchange 中找到的所有内容,但我不觉得这是重复的,因为我仍然无法让它工作。我的设置中有些地方不对,需要帮助。)
回答by Viach Kakovskyi
Here is verified example for Python REPL:
这是 Python REPL 的经过验证的示例:
>>> import subprocess
>>> import sys
>>> p = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(100)'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT); print('finished')
finished
How to verify that via another terminal window:
如何通过另一个终端窗口验证:
$ ps aux | grep python
Output:
输出:
user 32820 0.0 0.0 2447684 3972 s003 S+ 10:11PM 0:00.01 /Users/user/venv/bin/python -c import time; time.sleep(100)
回答by jfs
Popen()
starts a child process—it does not wait for it to exit. You have to call .wait()
method explicitly if you want to wait for the child process. In that sense, all subprocesses are background processes.
Popen()
启动一个子进程——它不会等待它退出。.wait()
如果要等待子进程,则必须显式调用方法。从这个意义上说,所有子进程都是后台进程。
On the other hand, the child process may inherit various properties/resources from the parent such as open file descriptors, the process group, its control terminal, some signal configuration, etc—it may lead to preventing ancestors processes to exit e.g., Python subprocess .check_call vs .check_outputor the child may die prematurely on Ctrl-C (SIGINT signal is sent to the foreground process group) or if the terminal session is closed (SIGHUP).
另一方面,子进程可能会从父进程继承各种属性/资源,例如打开的文件描述符、进程组、其控制终端、某些信号配置等——这可能会导致阻止祖先进程退出,例如Python 子进程.check_call 与 .check_output或者子进程可能在 Ctrl-C(SIGINT 信号被发送到前台进程组)或终端会话关闭 (SIGHUP) 时过早死亡。
To disassociate the child process completely, you should make it a daemon. Sometimes something in between could be enough e.g., it is enough to redirect the inherited stdout in a grandchild so that .communicate()
in the parent would return when its immediate child exits.
要完全解除子进程的关联,您应该将其设为 daemon。有时介于两者之间就足够了,例如,重定向孙子中继承的 stdout.communicate()
就足够了,以便在父子中的直接子进程退出时返回。