如何在Python中启动延迟调用的后台进程?

1 投票
2 回答
1298 浏览
提问于 2025-04-15 18:51

好的,这个问题有点复杂。我需要启动一个后台进程,这个进程要先等 N 秒,然后再执行某个命令。此外,我还需要获取这个后台进程的进程 ID(pid),因为当父进程结束时,如果需要的话,它会杀掉这个后台进程。用 shell 语法看起来大概是这样的:

  (sleep 15 && run_some_cmd) & # launch bg process
  bg_pid=$!                    # capture the bg pid
  # do some stuff here...     
  kill -9 $bg_pid              # and kill the bg_pid if necessary

这就是在 shell 中的启动方式。不过,我想用 Python 来实现。问题是,由于我需要获取后台进程的 pid,所以不能使用 os.system() 或 os.fork(),因为在这两种情况下,父进程都无法访问子进程的 pid。我正在尝试用 subprocess.Popen() 来实现,但由于有“sleep 15”这一部分,操作起来有点棘手。

有什么想法吗?

2 个回答

1

当你在使用 subprocess.Popen 时,把 shell 设置为 True,那么你执行的命令就可以和你在命令行中直接输入的一样。例如,像 (sleep 15 && run_some_cmd) 这样的命令是可以正常工作的。

3

我不能使用 os.system() 或 os.fork(),因为在这两种情况下,父进程无法获取子进程的 pid。

其实,父进程可以通过 fork() 的返回值来获取 pid。无论如何,我建议使用 subprocess 模块。这个模块让你可以通过 Popen 对象的 pid 属性来访问 pid。你还可以使用 os.kill() 函数向一个进程发送信号(比如杀掉它)。

最开始,我提到“subprocess 更好,因为它在 Windows 上也能用,而 fork() 不行”。这个评论几乎立刻就被删掉了,因为虽然 subprocess 模块可以用,但 os.kill() 在 Windows 上不行。不过,你可以通过为 Windows 定义一个 kill 函数来解决这个问题,具体可以参考 这里,还有(有点讽刺的是)亚历克斯·马特利自己在 这里 提到的。所以现在我可以说 subprocess 的一个优点是它更跨平台,这让它显得更酷。

当然,如果你使用亚历克斯·马特利对这个问题的回答,那么在 Windows 上运行的能力又会降低,因为你依赖于系统 shell 的一些功能(当然,cygwin 始终是一个选择)。

撰写回答