Python Daemonize Library
daemonize is a Python library designed to allow your code to run as a well-behaved daemon process on Unix-like systems. It simplifies the complex steps involved in daemonization, such as forking, session management, and PID file handling. The current version is 2.5.0, and it is actively maintained with releases occurring periodically, typically a few times a year or every couple of years.
Common errors
-
ImportError: No module named daemonize
cause The `daemonize` package is not installed or the Python environment where it's installed is not active.fixEnsure the library is installed using `pip install daemonize` and that you are running your script in the correct Python environment (e.g., a virtual environment). -
The daemon starts, but no logs appear after the initial startup messages, or the daemon process silently exits.
cause During daemonization, the operating system closes all inherited file descriptors by default. If your logging setup (or any other I/O) relies on an open file descriptor that wasn't explicitly preserved, it will cease to function or cause the daemon to crash.fixPass the file descriptors of your log files (e.g., `logging.FileHandler.stream.fileno()`) or other critical I/O resources to the `keep_fds` argument when initializing `Daemonize`. -
OSError: [Errno 13] Permission denied: '/path/to/daemon.pid'
cause The user attempting to run the daemon, or the user that the daemon process switches to, does not have write permissions to create or update the specified PID file.fixEnsure the directory containing the PID file (`/path/to/`) exists and is writable by the user account under which the daemon is intended to run. If dropping privileges with `user` or `group` parameters, ensure those specific users/groups have write access.
Warnings
- gotcha File descriptors (like log file handles, sockets) are typically closed during daemonization. If you want them to remain open and functional in the daemon process, you MUST explicitly pass their file descriptors to the `keep_fds` argument of the `Daemonize` constructor.
- breaking The `daemonize` library is designed exclusively for Unix-like operating systems (Linux, macOS, etc.) and will not function on Windows. Attempting to use it on Windows will result in errors related to missing POSIX functions (e.g., `os.fork`).
- gotcha Ensure the directory for the PID file (`pid` argument) exists and that the user the daemon runs as has write permissions to it. If not, the daemonization process will fail with a `Permission denied` error or similar.
Install
-
pip install daemonize
Imports
- Daemonize
from daemonize import Daemonize
Quickstart
import time
import os
import logging
from daemonize import Daemonize
# Configure logging BEFORE daemonization if you want it to persist
# The log file descriptor needs to be passed to keep_fds
log_file = "/tmp/test_daemon.log"
pid_file = "/tmp/test_daemon.pid"
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.propagate = False
fh = logging.FileHandler(log_file, "w")
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
keep_fds = [fh.stream.fileno()]
def main():
count = 0
while True:
logger.info(f"Daemon is running. Count: {count}")
count += 1
time.sleep(5)
if __name__ == "__main__":
# Ensure the PID directory exists
os.makedirs(os.path.dirname(pid_file), exist_ok=True)
# Initialize Daemonize object
daemon = Daemonize(
app="test_app",
pid=pid_file,
action=main,
keep_fds=keep_fds,
chdir="/",
verbose=True # Set to False for production
)
# Start the daemon. For debugging, you can call main() directly
# to run in foreground: main()
logger.info(f"Starting daemon '{daemon.app}' with PID file '{daemon.pid}'")
daemon.start()