如何在 Windows 上从 python 启动守护进程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12843903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to start daemon process from python on windows?
提问by zzandy
Can my python script spawn a process that will run indefinitely?
我的 python 脚本可以生成一个无限期运行的进程吗?
I'm not too familiar with python, nor with spawning deamons, so I cam up with this:
我不太熟悉 python,也不熟悉生成 deamons,所以我想出了这个:
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_NEW_CONSOLE
subprocess.Popen(executable, close_fds = True, startupinfo = si)
The process continues to run past python.exe, but is closed as soon as I close the cmd window.
该进程继续运行通过 python.exe,但在我关闭 cmd 窗口后立即关闭。
采纳答案by zzandy
Using the answerJanne Karila pointed out this is how you can run a process that doen't die when its parent dies, no need to use the win32processmodule.
使用答案Janne Karila 指出,这就是您如何运行一个在其父级死亡时不会死亡的进程,无需使用该win32process模块。
DETACHED_PROCESS = 8
subprocess.Popen(executable, creationflags=DETACHED_PROCESS, close_fds=True)
DETACHED_PROCESSis a Process Creation Flagthat is passed to the underlying CreateProcessfunction.
DETACHED_PROCESS是传递给底层CreateProcess函数的进程创建标志。
回答by Rahul Gautam
For that purpose you could daemonize your python process or as you are using windows environment you would like to run this as a windows service.
为此,您可以守护您的 python 进程,或者当您使用 Windows 环境时,您希望将其作为 Windows 服务运行。
You know i like to hate posting only web-links:
你知道我讨厌只发布网络链接:
But for more information according to your requirement:
但根据您的要求了解更多信息:
A simple way to implement Windows Service.read all comments it will resolve any doubt
一种实现 Windows 服务的简单方法。阅读所有评论,它将解决任何疑问
If you really want to learn more
如果你真的想了解更多
First read this
首先阅读这个
what is daemon process or creating-a-daemon-the-python-way
什么是守护进程或创建守护进程python-way
update:Subprocess is not the right way to achieve this kind of thing
更新:子流程不是实现这种事情的正确方法
回答by Nick Badger
This question was asked 3 years ago, and though the fundamental details of the answer haven't changed, given its prevalence in "Windows Python daemon" searches, I thought it might be helpful to add some discussion for the benefit of future Google arrivees.
这个问题是 3 年前提出的,尽管答案的基本细节没有改变,但考虑到它在“Windows Python 守护进程”搜索中的普遍性,我认为添加一些讨论可能会有所帮助,以利于未来的 Google 到来。
There are really two parts to the question:
这个问题实际上有两个部分:
- Can a Python script spawn an independent process that will run indefinitely?
- Can a Python script act like a Unix daemon on a Windows system?
- Python 脚本能否生成一个可以无限期运行的独立进程?
- Python 脚本可以像 Windows 系统上的 Unix 守护进程一样工作吗?
The answer to the first is an unambiguous yes; as already pointed out; using subprocess.Popenwith the creationflags=subprocess.CREATE_NEW_PROCESS_GROUPkeyword will suffice:
第一个问题的答案是明确的。正如已经指出的那样;subprocess.Popen与creationflags=subprocess.CREATE_NEW_PROCESS_GROUP关键字一起使用就足够了:
import subprocess
independent_process = subprocess.Popen(
'python /path/to/file.py',
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)
Note that, at least in my experience, CREATE_NEW_CONSOLEis not necessary here.
请注意,至少根据我的经验,CREATE_NEW_CONSOLE这里没有必要。
That being said, the behavior of this strategy isn't quite the same as what you'd expect from a Unix daemon. What constitutes a well-behaved Unix daemon is better explained elsewhere, but to summarize:
话虽如此,此策略的行为与您对 Unix 守护程序的期望并不完全相同。行为良好的 Unix 守护进程的构成在别处有更好的解释,但总结一下:
- Close open file descriptors (typically all of them, but some applications may need to protect some descriptors from closure)
- Change the working directory for the process to a suitable location to prevent "Directory Busy" errors
- Change the file access creation mask (
os.umaskin the Python world) - Move the application into the background and make it dissociate itself from the initiating process
- Completely divorce from the terminal, including redirecting
STDIN,STDOUT, andSTDERRto different streams (oftenDEVNULL), and prevent reacquisition of a controlling terminal - Handle signals, in particular,
SIGTERM.
- 关闭打开的文件描述符(通常是全部,但某些应用程序可能需要保护某些描述符不被关闭)
- 将进程的工作目录更改为合适的位置以防止“目录忙”错误
- 更改文件访问创建掩码(
os.umask在 Python 世界中) - 将应用程序移入后台并使其与启动进程分离
- 与终端完全分离,包括重定向
STDIN、STDOUT和STDERR到不同的流(通常DEVNULL),并防止重新获取控制终端 - 处理信号,尤其是
SIGTERM.
The reality of the situation is that Windows, as an operating system, really doesn't support the notion of a daemon: applications that start from a terminal (or in any other interactive context, including launching from Explorer, etc) will continue to run with a visible window, unless the controlling application (in this example, Python) has included a windowless GUI. Furthermore, Windows signal handling is woefully inadequate, and attempts to send signals to an independentPython process (as opposed to a subprocess, which would not survive terminal closure) will almost always result in the immediate exit of that Python process without any cleanup(no finally:, no atexit, no __del__, etc).
实际情况是,作为操作系统的 Windows 确实不支持守护进程的概念:从终端启动(或在任何其他交互式上下文中,包括从资源管理器启动等)的应用程序将继续运行具有可见窗口,除非控制应用程序(在本例中为 Python)包含一个无窗口 GUI。此外,Windows 信号处理严重不足,并且尝试将信号发送到独立的Python 进程(而不是子进程,它不会在终端关闭后继续存在)几乎总是导致该 Python 进程立即退出而不进行任何清理(不finally:、不atexit、__del__不等)。
Rolling your application into a Windows service, though a viable alternative in many cases, also doesn't quite fit. The same is true of using pythonw.exe(a windowless version of Pythonthat ships with all recent Windows Python binaries). In particular, they fail to improve the situation for signal handling, and they cannot easily launch an application from a terminal and interact with it during startup (for example, to deliver dynamic startup arguments to your script, say, perhaps, a password, file path, etc), before"daemonizing". Additionally, Windows services require installation, which -- though perfectly possible to do quickly at runtime when you first call up your "daemon" -- modifies the user's system (registry, etc), which would be highly unexpected if you're coming from a Unix world.
将您的应用程序滚动到 Windows 服务中,虽然在许多情况下是可行的替代方案,但也不太适合。使用pythonw.exe(与所有最新的 Windows Python 二进制文件一起提供的无窗口版本的 Python)也是如此。特别是,它们无法改善信号处理的情况,并且它们无法轻松地从终端启动应用程序并在启动期间与其交互(例如,将动态启动参数传递给您的脚本,例如密码、文件路径等),之前“恶魔化”。此外,Windows 服务需要安装,尽管在您第一次调用“守护程序”时在运行时可以快速完成安装,但它会修改用户的系统(注册表等),如果您来自一个 Unix 世界。
In light of that, I would argue that launching a pythonw.exesubprocess using subprocess.CREATE_NEW_PROCESS_GROUPis probably the closest Windows equivalent for a Python process to emulate a traditional Unix daemon.However, that still leaves you with the added challenge of signal handling and startup communications (not to mention making your code platform-dependent, which is always frustrating).
有鉴于此,我认为使用启动pythonw.exe子subprocess.CREATE_NEW_PROCESS_GROUP进程可能是 Python 进程模拟传统 Unix 守护进程的最接近的 Windows 等价物。但是,这仍然会给您带来信号处理和启动通信的额外挑战(更不用说让您的代码依赖于平台,这总是令人沮丧)。
That all being said, for anyone encountering this problem in the future, I've rolled a library called daemonikerthat wraps both proper Unix daemonization andthe above strategy. It also implements signal handling (for both Unix and Windows systems), and allows you to pass objects to the "daemon" process using pickle. Best of all, it has a cross-platform API:
话虽如此,对于将来遇到此问题的任何人,我推出了一个名为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()

