在Python中运行后台进程,不要等待

在Python中运行后台进程,不要等待,python,subprocess,background-process,popen,Python,Subprocess,Background Process,Popen,我的目标很简单:启动rsync,不要等待 基于Debian的Python 2.7.9 示例代码: 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_r

我的目标很简单:启动rsync,不要等待

基于Debian的Python 2.7.9

示例代码:

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"
(我之所以注释掉执行命令,是因为我实际上在代码中保留了所有的试用,以便知道我做了什么和没有做什么。显然,我会在运行脚本时不注释右边的行。)

发生的事情是这样的……我可以在服务器上观看传输,当传输完成后,我会在屏幕上打印“完成”

我希望在发出
rsync
命令并开始传输后立即打印“DONE”

看起来很直截了当。我已经关注了其他帖子中概述的细节,比如《一个和一个》,但有些事情阻止了它对我的作用

提前谢谢


(我已经尝试了在StackExchange中可以找到的一切,但我觉得这不是重复的,因为我仍然无法让它工作。我的设置中有些不正确,需要帮助。)

下面是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
如何通过另一个终端窗口验证:

$ ps aux | grep python
输出:

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)
Popen()
启动子进程,而不是等待它退出。如果要等待子进程,必须显式调用
.wait()
方法。从这个意义上讲,所有子流程都是后台流程

另一方面,子进程可以从父进程继承各种属性/资源,例如打开的文件描述符、进程组、其控制终端、一些信号配置等,这可能导致阻止父进程退出,例如,或者子进程可能在Ctrl-C上过早死亡(SIGINT信号发送到前台进程组)或如果终端会话关闭(SIGHUP)


要完全解除子进程的关联,您应该将其设置为。有时介于两者之间的内容就足够了,例如,就足够了。

在使用qnx设备时,我遇到了类似的问题,希望有一个子进程独立于主进程运行,甚至在主进程终止后运行。 以下是我发现的实际有效的解决方案“creationflags=subprocess.DETACHED_PROCESS”:

import subprocess
import time

pid = subprocess.Popen(["python", "path_to_script\turn_ecu_on.py"], creationflags=subprocess.DETACHED_PROCESS)

time.sleep(15)
print("Done")

指向文档的链接:

似乎问题得到了回答@viach的指针是你最好的选择。上面说的“creationflags”仅适用于Windows。你提供的链接也谈到了Win32。你是否尝试过简化代码以了解问题真正出在何处?
subprocess.call(“sleep 10.split())
在代码中有一个明显的延迟,而
subprocess.Popen(“sleep 10.split())
立即进入下一行。也许你的问题在其他地方,很难看到?如果你将rsync调用更改为简单的sleep调用,你的代码是否工作(在计时方面)?无关:这一点没用“没有对我有用的东西”除非你展示了失败的确切代码示例,描述你期望它做什么,以及一步一步地发生什么。这在解释器中也对我有用,但对我的脚本不起作用。我必须开始将其分解为零并重新构建。我还将尝试
Process()
根据上面@asav的建议。如您的示例所示,我在调用Popen后在日志中打印了一条消息,我在日志中看到了我的消息。问题在我尚未找到的其他地方,但与往常一样,您的建议帮助我确定Popen不是问题所在。感谢您的帮助!我正在使用
p=子进程(rsync_dict,close_fds=True)
它是否如广告所示工作。@harperville我觉得这种行为的原因在于您的命令,它可能在等待来自
stdin
的一些输入。请使用stdout=DEVNULL而不是stdout=PIPE,否则当操作系统管道缓冲区填满时,子进程可能会暂停。jfs的回答意味着只需创建
Pope的实例n
使其自行分离,或者至少不会让python脚本等待。如果是这样,为什么您的答案看起来比这复杂得多?另外,在最初的问题中,您发布了一个引用操作系统依赖性的链接。您的答案是否与操作系统无关?是否有办法继续发送正在运行的进程数据/命令?@CharlieParker当然,你知道为什么这个标志在ubuntu python3.7上不起作用吗?因为根据代码,子流程模块只为win32平台和python 3.7及以上版本定义了这个标志。它是一个windows常量()