如何从Windows上的python启动守护进程?

zza*_*ndy 8 python windows daemon

我的python脚本可以产生一个无限期运行的进程吗?

我不太熟悉python,也不熟悉产生deamons,所以我想到了这个:

si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_NEW_CONSOLE
subprocess.Popen(executable, close_fds = True, startupinfo = si)
Run Code Online (Sandbox Code Playgroud)

该过程继续运行python.exe,但是一关闭cmd窗口就会关闭.

zza*_*ndy 14

使用答案 Janne Karila指出这是如何运行一个过程,当它的父亲死亡时不会死,不需要使用该win32process模块.

DETACHED_PROCESS = 8
subprocess.Popen(executable, creationflags=DETACHED_PROCESS, close_fds=True)
Run Code Online (Sandbox Code Playgroud)

DETACHED_PROCESS是一个进程创建标志,传递给底层的CreateProcess函数.


Nic*_*ger 11

这个问题是3年前提出的,虽然答案的基本细节没有改变,但鉴于其在"Windows Python守护程序"搜索中的普及,我认为为未来的Google到达者的利益添加一些讨论可能会有所帮助.

问题实际上有两个部分:

  1. Python脚本能否产生一个无限运行的独立进程?
  2. Python脚本可以像Windows系统上的Unix守护程序一样吗?

第一个问题的答案是明确无误的; 正如已经指出的那样; 采用subprocess.Popencreationflags=subprocess.CREATE_NEW_PROCESS_GROUP关键字就足够了:

import subprocess

independent_process = subprocess.Popen(
    'python /path/to/file.py',
    creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)
Run Code Online (Sandbox Code Playgroud)

请注意,至少在我的经验中,CREATE_NEW_CONSOLE这里没有必要.

话虽这么说,这个策略的行为与你对Unix守护进程的期望并不完全相同.什么构成一个表现良好的Unix守护进程在其他地方更好的解释,但总结一下:

  1. 关闭打开的文件描述符(通常是所有这些描述符,但是某些应用程序可能需要保护某些描述符不被关闭)
  2. 将进程的工作目录更改为合适的位置以防止"目录繁忙"错误
  3. 更改文件访问创建掩码(os.umask在Python世界中)
  4. 将应用程序移动到后台,使其与启动过程分离
  5. 完全离开终端,包括重定向STDIN,STDOUTSTDERR不同的流(经常DEVNULL),并防止重新获取控制终端
  6. 特别是处理信号SIGTERM.

这种情况的实际情况是,Windows作为一个操作系统,实际上不支持守护进程的概念:从终端(或任何其他交互式环境,包括从资源管理器启动等)开始的应用程序将继续运行除了控制应用程序(在本例中为Python)包含无窗口GUI之外,还有一个可见窗口.此外,Windows信号处理非常不合适,并且尝试将信号发送到独立的 Python进程(与子进程相反,这不会终止关闭)将几乎总是导致该进程立即退出而不进行任何清理(否)finally:,不atexit,不__del__,等等.

将应用程序滚动到Windows服务中虽然在许多情况下是可行的替代方案,但也不太合适.使用pythonw.exe(所有最新的Windows Python二进制文件附带的无窗口版本的Python)也是如此.特别是,它们无法改善信号处理的情况,并且它们无法轻松地从终端启动应用程序并在启动期间与其进行交互(例如,为您的脚本提供动态启动参数,例如,可能是密码,文件路径等), "守护" 之前.此外,Windows服务需要安装,虽然完全可以在第一次调用"守护程序"时在运行时快速完成 - 修改用户的系​​统(注册表等),如果您来自此处,这将是非常意外的一个Unix世界.

鉴于此,我认为启动pythonw.exesubprocess.CREATE_NEW_PROCESS_GROUP进程可能是最接近的Windows等效的Python进程来模拟传统的Unix守护进程.但是,这仍然会给您带来信号处理和启动通信的额外挑战(更不用说使您的代码平台依赖,这总是令人沮丧).

总而言之,对于将来遇到此问题的任何人,我已经推出了一个名为daemoniker的库,它包含了正确的Unix守护进程上述策略.它还实现了信号处理(适用于Unix和Windows系统),并允许您使用pickle将对象传递给"守护进程"进程.最重要的是,它有一个跨平台的API:

from daemoniker import Daemonizer

with Daemonizer() as (is_setup, daemonizer):
    if is_setup:
        # This code is run before daemonization.
        do_things_here()

    # We need to explicitly pass resources to the daemon; other variables
    # may not be correct
    is_parent, my_arg1, my_arg2 = daemonizer(
        path_to_pid_file,
        my_arg1,
        my_arg2
    )

    if is_parent:
        # Run code in the parent after daemonization
        parent_only_code()

# We are now daemonized, and the parent just exited.
code_continues_here()
Run Code Online (Sandbox Code Playgroud)


Rah*_*tam 5

为此,您可以守护您的python进程,或者当您使用Windows环境时,您希望将其作为Windows服务运行.

你知道我喜欢只发布网页链接:

但是根据您的要求获取更多信息:

一种实现Windows服务的简单方法.阅读所有评论,它将解决任何疑问

如果你真的想了解更多

首先读这个

什么是守护进程或创建-a-daemon-the-python-way

更新: 子进程不是实现此类事情的正确方法