【问题标题】:How to start daemon process from python on windows?如何在 Windows 上从 python 启动守护进程?
【发布时间】:2012-10-02 08:58:33
【问题描述】:

我的 python 脚本能否生成一个无限期运行的进程?

我对 python 不太熟悉,对生成恶魔也不太熟悉,所以我想出了这个:

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 窗口后立即关闭。

【问题讨论】:

标签: python windows daemon


【解决方案1】:

使用answer Janne Karila 指出,这是您可以运行在其父进程死亡时不会死亡的进程的方法,无需使用win32process 模块。

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

DETACHED_PROCESS 是一个Process Creation Flag,它被传递给底层的CreateProcess 函数。

【讨论】:

【解决方案2】:

这个问题是 3 年前提出的,虽然答案的基本细节没有改变,但考虑到它在“Windows Python 守护进程”搜索中的普遍性,我认为添加一些讨论可能会对未来有所帮助谷歌来了。

这个问题实际上有两个部分:

  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 守护进程的期望并不完全相同。 better explained elsewhere 构成了一个行为良好的 Unix 守护进程,但总结一下:

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

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

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

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

话虽如此,对于将来遇到此问题的任何人,我推出了一个名为 daemoniker 的库,它包含了正确的 Unix 守护进程上述策略。它还实现了信号处理(适用于 Unix 和 Windows 系统),并允许您使用 pickle 将对象传递给“守护进程”进程。最重要的是,它有一个cross-platform 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()

【讨论】:

  • High Nick,尝试一下,看看我是否可以移植一个仅限 linux 的脚本以跨平台依赖。以前使用 python-daemon,将报告它的进展情况!在您的帖子顶部添加一个提及您的图书馆的注释可能是一个想法,以便寻找答案的人可以更轻松地看到它:)
【解决方案3】:

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

你知道我讨厌只发布网络链接:

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

A simple way to implement Windows Service.阅读所有cmets它将解决任何疑问

如果你真的想了解更多

首先阅读本文

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

更新: 子流程不是实现这种事情的正确方法

【讨论】:

  • 谢谢,但我不想要服务,事实上我不能使用,因为有人告诉我不要。
  • 很高兴知道,另一个答案的链接适合您。但是对于您的信息,我想让您完全了解它是如何完成的,感染它您打开 suprocess.py(并从第 599 行开始阅读)您将与创建守护进程一样,但现在我确实认为 popen 对你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
相关资源
最近更新 更多