繁体   English   中英

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

[英]How to start daemon process from python on windows?

我的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)

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

使用答案 Janne Karila指出,这是如何运行一个在其父级死亡时不会死的过程,不需要使用win32process模块。

DETACHED_PROCESS = 8
subprocess.Popen(executable, creationflags=DETACHED_PROCESS, close_fds=True)

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

这个问题是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
)

请注意,至少根据我的经验,此处不需要CREATE_NEW_CONSOLE

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

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

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

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

在鉴于此,我认为,推出pythonw.exe使用子subprocess.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()

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

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

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

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

如果你真的想了解更多

首先读这个

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM