如何实现一个简单的跨平台Python守护进程?
我想让我的 Python 程序在 Windows 或 Unix 上作为守护进程在后台运行。我看到 python-daemon 包 仅适用于 Unix;有跨平台的替代方案吗?如果可能的话,我希望代码尽可能简单。
I would like to have my Python program run in the background as a daemon, on either Windows or Unix. I see that the python-daemon package is for Unix only; is there an alternative for cross platform? If possible, I would like to keep the code as simple as I can.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 Windows 中,它被称为“服务”,您可以很容易地实现它,例如使用 win32serviceutil 模块,该模块是 pywin32。不幸的是,这两个“心理模型”——服务与守护进程——在细节上有很大不同,尽管它们服务于相似的目的,而且据我所知,没有 Python 外观试图将它们统一到一个框架中。
In Windows it's called a "service" and you could implement it pretty easily e.g. with the win32serviceutil module, part of pywin32. Unfortunately the two "mental models" -- service vs daemon -- are very different in detail, even though they serve similar purposes, and I know of no Python facade that tries to unify them into a single framework.
这个问题已经有 6 年历史了,但我也遇到了同样的问题,并且现有的答案对于我的用例来说不够跨平台。尽管 Windows 服务的使用方式通常与 Unix 守护程序类似,但归根结底,它们之间存在很大差异,“细节决定成败”。长话短说,我开始尝试找到一些东西,让我能够在 Unix 和 Windows 上运行完全相同的应用程序代码,同时满足对行为良好的 Unix 守护进程的期望(即 在其他地方有更好的解释)在两个平台上尽可能最好:
os.umask
) world)STDIN
、STDOUT
和STDERR 到不同的流(通常是
DEVNULL
),并防止重新获取控制终端SIGTERM
。跨平台守护进程的根本问题是,Windows 作为一个操作系统,实际上不支持守护进程的概念:从终端启动的应用程序(或在任何其他交互式上下文中,包括从资源管理器启动等)将继续使用可见窗口运行,除非控制应用程序(在本例中为 Python)包含无窗口 GUI。此外,Windows 信号处理严重不足,尝试将信号发送到独立的 Python 进程(而不是子进程,子进程无法在终端关闭中幸存)几乎总是会导致该进程立即退出Python 进程没有任何清理(没有
finally:
、没有atexit
、没有__del__
等)。Windows 服务(尽管在许多情况下是可行的替代方案)对我来说基本上是不可能的:它们不是跨平台的,并且需要修改代码。
pythonw.exe
(Python 的无窗口版本,随所有最新的 Windows Python 二进制文件一起提供)是更接近,但它仍然没有完全成功:特别是,它无法改善信号处理的情况,并且您仍然无法轻松地从终端启动pythonw.exe
应用程序并与它在启动期间(例如,向脚本传递动态启动参数,例如密码、文件路径等),在“守护进程”之前。最后,我决定使用
subprocess.Popen
和creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
关键字来创建一个独立的无窗口进程:但是,这仍然给我留下了添加的内容启动通信和信号处理的挑战。对于前者,我的策略是:
pickle
启动进程命名空间的重要部分tempfile
中对于信号处理,我必须更有创意。在“守护进程”进程中:
总而言之,对于将来遇到此问题的任何人,我推出了一个名为 daemoniker 将适当的 Unix 守护进程和上述 Windows 策略包装到一个统一的外观中。 跨平台 API 如下所示:
This question is 6 years old, but I had the same problem, and the existing answers weren't cross-platform enough for my use case. Though Windows services are often used in similar ways as Unix daemons, at the end of the day they differ substantially, and "the devil's in the details". Long story short, I set out to try and find something that allows me to run the exact same application code on both Unix and Windows, while fulfilling the expectations for a well-behaved Unix daemon (which is better explained elsewhere) as best as possible on both platforms:
os.umask
in the Python world)STDIN
,STDOUT
, andSTDERR
to different streams (oftenDEVNULL
), and prevent reacquisition of a controlling terminalSIGTERM
.The fundamental problem with cross-platform daemonization 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 independent Python 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:
, noatexit
, no__del__
, etc).Windows services (though a viable alternative in many cases) were basically out of the question for me: they aren't cross-platform, and they're going to require code modification.
pythonw.exe
(a windowless version of Python that ships with all recent Windows Python binaries) is closer, but it still doesn't quite make the cut: in particular, it fails to improve the situation for signal handling, and you still cannot easily launch apythonw.exe
application from the 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".In the end, I settled on using
subprocess.Popen
with thecreationflags=subprocess.CREATE_NEW_PROCESS_GROUP
keyword to create an independent, windowless process:However, that still left me with the added challenge of startup communications and signal handling. Without going into a ton of detail, for the former, my strategy was:
pickle
the important parts of the launching process' namespacetempfile
For signal handling I had to get a bit more creative. Within the "daemonized" process:
That all being said, for anyone encountering this problem in the future, I've rolled a library called daemoniker that wraps both proper Unix daemonization and the above Windows strategy into a unified facade. The cross-platform API looks like this:
我想到了两个选择:
将程序移植到 Windows 服务。您可能可以在两个实现之间共享大部分代码。
您的程序真的使用任何守护程序功能吗?如果没有,您将其重写为在后台运行的简单服务器,通过套接字管理通信并执行其任务。它可能会比守护程序消耗更多的系统资源,但它将独立于引用平台。
Two options come to mind:
Port your program into a windows service. You can probably share much of your code between the two implementations.
Does your program really use any daemon functionality? If not, you rewrite it as a simple server that runs in the background, manages communications through sockets, and perform its tasks. It will probably consume more system resources than a daemon would, but it would be quote platform independent.
一般来说,守护进程的概念是 Unix 特定的,特别是关于文件创建掩码、进程层次结构和信号处理的预期行为。
您可能会发现 PEP 3143 很有用,其中建议延续 python-daemon 被考虑用于 Python 3.2,并且许多 相关守护进程模块和实现进行了讨论。
In general the concept of a daemon is Unix specific, in particular expected behaviour with respect to file creation masks, process hierarchy, and signal handling.
You may find PEP 3143 useful wherein a proposed continuation of python-daemon is considered for Python 3.2, and many related daemonizing modules and implementations are discussed.
它只是unix的原因是守护进程是Unix特定的概念,即后台进程由操作系统启动,通常作为根 PID 的子进程运行。
Windows 没有直接相当于 unix 守护进程,我能想到的最接近的是 Windows 服务。
有一个名为 pythonservice.exe for windows 的程序。不确定是否所有版本的 python 都支持它
The reason it's unix only is that daemons are a Unix specific concept i.e a background process initiated by the os and usually running as a child of the root PID .
Windows has no direct equivalent of a unix daemon, the closest I can think of is a Windows Service.
There's a program called pythonservice.exe for windows . Not sure if it's supported on all versions of python though