Вы можете использовать словари для этого. Словари - это хранилища ключей и ценностей.
>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2
Вы можете использовать имена переменных ключей для достижения эффекта переменных переменных без риска для безопасности.
>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'
В тех случаях, когда вы думаете сделать что-то вроде
var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...
список может быть более подходящим, чем dict. Список представляет упорядоченную последовательность объектов с целыми индексами:
l = ['foo', 'bar', 'baz']
print(l[1]) # prints bar, because indices start at 0
l.append('potatoes') # l is now ['foo', 'bar', 'baz', 'potatoes']
Для упорядоченных последовательностей списки удобнее, чем dict с целыми ключами, потому что списки поддерживают итерацию в порядке индекса, slicing , append
и другие операции, которые потребуют неудобного управления ключами с помощью dict.
Текущее решение
Справочная реализация PEP 3143 (библиотека стандартного демона) теперь доступна как python-daemon .
Исторический ответ
Вот мой базовый демон Python «Howdy World», с которого я начинаю работать, когда я разрабатываю новое приложение-демон.
#!/usr/bin/python
import time
from daemon import runner
class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/foo.pid'
self.pidfile_timeout = 5
def run(self):
while True:
print("Howdy! Gig'em! Whoop!")
time.sleep(10)
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
Обратите внимание, что вам понадобится библиотека python-daemon
. Вы можете установить его на:
pip install python-daemon
Затем просто запустите его с помощью ./howdy.py start
и остановите его с помощью ./howdy.py stop
.
daemon
, который вы импортируете, не является стандартной частью Python (пока). Он должен быть установлен с pip install python-daemon
или эквивалентным.
– Nate
11 February 2012 в 01:50
После нескольких лет и многих попыток, теперь я понимаю, что есть лучший способ, чем начать, остановить, перезапустить демон прямо с Python: вместо этого используйте инструменты ОС!
Короче говоря, вместо выполнения python myapp start
и python myapp stop
, я делаю это, чтобы запустить приложение:
screen -S myapp python myapp.py
CTRL+A, D to detach
или screen -dmS myapp python myapp.py
до начать и отделить его в одной команде .
Затем:
screen -r myapp
снова подключиться к этому терминалу. После этого в терминале можно использовать CTRL + C, чтобы остановить его.
Есть множество проблем, которые нужно заботиться, когда вы становитесь хорошим процессом демона :
chroot
gaol suid
, sgid
init
, inetd
и т. д. stdin
, stdout
, stderr
, поскольку процесс демона больше не имеет управляющего терминала Некоторые из них являются стандартными, как описано в канонической литературе Unix ( Advanced Programming in UNIX Environment , покойным У. Ричардом Стивенсом, Addison-Wesley, 1992). Другие, такие как перенаправление потока и PID-обработка файлов , являются обычным поведением, которое ожидали бы большинство демонов, но это менее стандартизировано.
Все они покрываются PEP 3143 «Стандартная библиотека процессов демона». Реализация ссылок python-daemon работает на Python 2.7 или новее, а Python 3.2 или более поздней.
Альтернатива - создать нормальную, не-демонанизированную программу Python, а затем демонтировать ее извне с помощью supervisord . Это может сэкономить много головных болей и является * nix- и языковым переносом.
Я изменил несколько строк в примере кода Sander Marechal (упомянутый @JeffBauer в принятом ответе ), чтобы добавить метод quit()
, который выполняется до того, как демон остановлен. Это иногда очень полезно.
Примечание: я не использую модуль «python-daemon», потому что документация по-прежнему отсутствует (см. также много других вопросов SO) и довольно неясна (как правильно запустить / остановить демона из командной строки с помощью этого модуля?)
Эта функция преобразует приложение в демона:
import sys
import os
def daemonize():
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open(os.devnull, 'w')
se = open(os.devnull, 'w')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
Вероятно, не прямой ответ на вопрос, но systemd можно использовать для запуска вашего приложения в качестве демона. Вот пример:
[Unit]
Description=Python daemon
After=syslog.target
After=network.target
[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py
# Give the script some time to startup
TimeoutSec=300
[Install]
WantedBy=multi-user.target
Я предпочитаю этот метод, потому что большая часть работы выполняется для вас, а затем ваш сценарий демона ведет себя аналогично остальной системе.
-Orby
Еще одна вещь, о которой нужно подумать о демонализации в python:
Если вы используете ведение журнала python и хотите продолжить использовать его после демонтизации, обязательно вызовите close()
на обработчиках (в частности, обработчики файлов).
Если вы этого не сделаете, обработчик все еще может считать, что файлы открыты, а ваши сообщения просто исчезнут - другими словами, убедитесь, что регистратор знает, что его файлы закрыты!
Это предполагает, что когда вы демоннизируете, вы закрываете ВСЕ дескрипторы открытых файлов неразборчиво - вместо этого вы можете попытаться закрыть все, кроме файлов журнала (но обычно проще закрыть все, а затем снова открыть те, которые вы хотите).
80% времени, когда люди говорят «демона», им нужен только сервер. Поскольку вопрос совершенно неясен в этом вопросе, трудно сказать, какова возможная область ответов. Так как сервер достаточно, начните там. Если фактический «демон» действительно необходим (это редко), прочитайте в nohup
как способ демонстрации сервера.
До тех пор, пока фактический демон фактически не понадобится, просто напишите простой сервер.
Также посмотрите на реализацию WSGI reference .
Также посмотрите на Simple HTTP Server .
«Есть ли какие-то дополнительные вещи, которые нужно учитывать?» Да. Около миллиона вещей. Какой протокол? Сколько запросов? Как долго обслуживать каждый запрос? Как часто они прибудут? Будете ли вы использовать выделенный процесс? Потоки? Подпроцессы? Написание демона - большая работа.
fork()
, не говоря уже о двух. Они не имеют никакого отношения к демонализации.
– Brandon Rhodes
22 October 2010 в 17:31
crond
или syslogd
- выполняет домашние службы для всей системы. Чтобы создать процесс демона, необходимо, по крайней мере, выполнить double- fork()
, когда все дескрипторы файлов закрыты, так что он невосприимчив к сигналам всех управляющих терминалов, включая системную консоль. См. Ответ bignose.
– Brandon Rhodes
6 September 2011 в 05:08
SimpleHTTPServer
на самом деле является сервером, но тот, который не знает, как его демонизировать (например, вы можете использовать Ctrl-C). nohup
- это утилита для демонстрации наивного процесса, поэтому ваш nohupped сервер действительно и i> сервер daemon и i>, как вы утверждаете. Этот вопрос о переполнении стека по существу задавал вопрос: «Как я могу реализовать nohup
в Python?»
– Brandon Rhodes
7 September 2011 в 15:40
nohup
- прекрасный инструмент, и я удалю свой -1 голос, если вы просто переместите эту полезную идею в свой фактический ответ. На самом деле, если вы упомянете supervisord
и как он также сохранит автора от необходимости ведения журнала, сценария начала-остановки и перезапускает дросселирование, тогда я вам даже сделаю +1. :)
– Brandon Rhodes
8 September 2011 в 14:41
Боюсь, модуль демонов, упомянутый @Dustin, не работает для меня. Вместо этого я установил python-daemon и использовал следующий код:
# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass
with daemon.DaemonContext():
moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.
Запуск легко
> python myDaemon.py
только для полноты здесь - содержимое каталога образцового модуля
>ls samplemodule
__init__.py __init__.pyc moduleclass.py
Содержимое moduleclass.py может быть
class moduleclass():
...
def do_running():
m = moduleclass()
# do whatever daemon is required to do.
, поскольку python-daemon еще не поддерживает python 3.x, и из того, что можно прочитать в списке рассылки, он, возможно, никогда не будет, я написал новую реализацию PEP 3143: pep3143daemon
pep3143daemon должен поддерживать как минимум python 2.6, 2.7 и 3.x
Он также содержит класс PidFile.
Библиотека зависит только от стандартной библиотеки и на шести модулях.
Его можно использовать как замену для python-daemon.
Самый простой способ создания демона с Python - использовать фреймворк Twisted . Он обрабатывает все необходимое для демонализации. Он использует шаблон Reactor Pattern для обработки параллельных запросов.
Обратите внимание на пакет python-daemon , который решает множество проблем, стоящих за демонами.
Среди других функций он позволяет (из описания пакета Debian):
quit()
, который выполняется перед тем как демон будет остановлен. Вот он. – Basj 12 November 2016 в 11:30