这个问题是3年前提出的,虽然答案的基本细节没有改变,但考虑到它在“Windows Python守护进程”搜索中的普遍性,我认为增加一些讨论有助于未来的谷歌用户。这个问题实际上包含了两部分:
1. Python脚本可以生成一个独立的进程并运行无限长时间吗?
2. Python脚本能在Windows系统上像Unix守护进程一样运行吗?
第一个问题的答案是肯定的; 如已指出;使用带有`creationflags=subprocess.CREATE_NEW_PROCESS_GROUP`关键字的 `subprocess.Popen` 即可。
第二个问题需要更多的解释。
import subprocess
independent_process = subprocess.Popen(
'python /path/to/file.py',
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)
请注意,至少在我的经验中,此处不需要使用
CREATE_NEW_CONSOLE
。
话虽如此,这种策略的行为与Unix守护进程的预期行为并不完全相同。什么是良好的Unix守护进程在
其他地方更好地解释,但总结起来:
- 关闭打开的文件描述符(通常是所有文件描述符,但某些应用程序可能需要保护一些文件描述符以免被关闭)
- 将进程的工作目录更改为适当的位置,以防止“目录繁忙”错误
- 更改文件访问创建掩码(Python世界中的
os.umask
)
- 将应用程序移动到后台,并使其与启动进程分离
- 完全脱离终端,包括将
STDIN
、STDOUT
和STDERR
重定向到不同的流(通常是DEVNULL
),并防止重新获取控制终端
- 处理信号,特别是
SIGTERM
。
The reality of the situation is that Windows,作为一个操作系统,实际上并不支持守护进程的概念:从终端启动(或从资源管理器等任何交互式上下文中启动)的应用程序将继续显示窗口运行,除非控制应用程序(在此示例中为Python)包含无窗口GUI。此外,Windows信号处理功能非常不足,尝试向独立的Python进程(而不是子进程,后者在终端关闭后不会存活)发送信号几乎总会导致该Python进程立即退出,而没有任何清理(没有finally:,没有atexit,没有__del__等)。
将应用程序转换为Windows服务虽然在许多情况下是可行的替代方案,但并不完全适合。同样适用于使用pythonw.exe
(一种与所有最近的Windows Python二进制文件捆绑在一起的无窗口版本的Python)。特别是它们不能改善信号处理的情况,并且不能轻松地从终端启动应用程序并在启动期间与其进行交互(例如,向脚本提供动态启动参数,例如密码、文件路径等),在"daemonizing"之前。此外,Windows服务需要安装,在第一次调用"daemon"时可以快速运行时进行安装,但这会修改用户的系统(注册表等),如果您来自Unix世界,则这可能会令人意外。
考虑到这一点,我认为使用subprocess.CREATE_NEW_PROCESS_GROUP
启动pythonw.exe
子进程可能是Python进程在Windows上模拟传统Unix守护进程的最接近等效方式。但是,这仍然需要解决信号处理和启动通信的附加挑战(更不用说使您的代码平台相关,这总是令人沮丧的)。
话虽如此,对于将来遇到这个问题的任何人,我已经编写了一个名为 daemoniker 的库,它包装了正确的Unix守护进程化和上述策略。 它还实现了信号处理(适用于Unix和Windows系统),并允许您使用pickle将对象传递给“守护程序”进程。 最重要的是,它具有跨平台API:
from daemoniker import Daemonizer
with Daemonizer() as (is_setup, daemonizer):
if is_setup:
do_things_here()
is_parent, my_arg1, my_arg2 = daemonizer(
path_to_pid_file,
my_arg1,
my_arg2
)
if is_parent:
parent_only_code()
code_continues_here()