Удостоверьтесь, что только единственный экземпляр программы работает

Существует ли Pythonic способ иметь только один экземпляр выполнения программы?

Единственное разумное решение, которое я предложил, пытается выполнить его как сервер на некотором порте, затем вторая программа, пытающаяся связывать с тем же портом - сбои. Но это не действительно прекрасная идея, возможно, существует что-то более легкое, чем это?

(Учтите, что программа, как ожидают, иногда перестанет работать, т.е. segfault - таким образом, вещи как "файл блокировки" не будут работать),

112
задан Mike 3 July 2019 в 20:13
поделиться

6 ответов

Используя файл блокировки довольно общий подход на Unix. Если это отказывает, необходимо вымыться вручную. Вы могли stor PID в файле, и на проверке запуска, если существует процесс с этим PID, переопределяя файл блокировки если нет. (Однако Вам также нужна блокировка вокруг read-file-check-pid-rewrite-file). Вы найдете то, в чем Вы нуждаетесь для получения и проверки изодромного с предварением в os - пакет. Распространенный способ проверить, существует ли там процесс с данным изодромным с предварением, состоит в том, чтобы отправить ему нефатальный сигнал.

Другие альтернативы могли комбинировать это со скоплением или posix семафорами.

Открытие сетевой сокет, как saua предложенный, вероятно, был бы самым легким и самым портативным.

3
ответ дан Rolf Rander 24 November 2019 в 02:50
поделиться

Это может работать.

  1. Попытка создают файл PID к известному местоположению. Если Вы перестали работать, кому-то заблокировали файл, Вы сделаны.

  2. , Когда Вы обычно заканчиваете, закройте и удалите файл PID, таким образом, кто-то еще может перезаписать его.

можно обернуть программу в сценарии оболочки, который удаляет файл PID, даже если программа отказывает.

можно, также, использовать файл PID для закрытия программы, если это зависает.

5
ответ дан S.Lott 24 November 2019 в 02:50
поделиться

Вы уже нашли ответ на подобный вопрос в другом потоке, таким образом, для пользы полноты видят, как достигнуть того же на нелугу Windows, названном взаимным исключением.

http://code.activestate.com/recipes/474070/

6
ответ дан zgoda 24 November 2019 в 02:50
поделиться

Используйте изодромный с предварением файл. Вы имеете некоторое известное расположение, "/path/to/pidfile", и при запуске Вы делаете что-то вроде этого (частично псевдокод, потому что я - предварительный кофе и не хочу работать все что трудно):

import os, os.path
pidfilePath = """/path/to/pidfile"""
if os.path.exists(pidfilePath):
   pidfile = open(pidfilePath,"r")
   pidString = pidfile.read()
   if <pidString is equal to os.getpid()>:
      # something is real weird
      Sys.exit(BADCODE)
   else:
      <use ps or pidof to see if the process with pid pidString is still running>
      if  <process with pid == 'pidString' is still running>:
          Sys.exit(ALREADAYRUNNING)
      else:
          # the previous server must have crashed
          <log server had crashed>
          <reopen pidfilePath for writing>
          pidfile.write(os.getpid())
else:
    <open pidfilePath for writing>
    pidfile.write(os.getpid())

Так, другими словами, Вы проверяете, существует ли pidfile; в противном случае запишите свое изодромное с предварением в тот файл. Если pidfile действительно существует, то проверьте, чтобы видеть, является ли изодромным с предварением изодромный с предварением из рабочего процесса; если так, тогда Вы имеете другое живое выполнение процесса, поэтому просто закрываетесь. В противном случае тогда предыдущий разрушенный процесс, так зарегистрируйте его, и затем запишите Ваше собственное изодромное с предварением в файл вместо старого. Тогда продолжите.

10
ответ дан Charlie Martin 24 November 2019 в 02:50
поделиться

Я не знаю, является ли это pythonic достаточно, но в мире Java, слушающем на определенном порте, симпатичное широко используемое решение, поскольку это работает над всеми основными платформами и не имеет никаких проблем с отказывающими программами.

Другое преимущество слушания порта состоит в том, что Вы могли отправить команду в рабочий экземпляр. Например, когда пользователи запускают программу во второй раз, когда Вы могли отправить рабочему экземпляру команду, чтобы сказать ей открывать другое окно (это - то, что Firefox делает, например. Я не знаю, используют ли они порты TCP или именованные каналы или что-то как этот, 'хотя).

23
ответ дан Joachim Sauer 24 November 2019 в 02:50
поделиться

Простой, межплатформенное решение, найденное в другой вопрос zgoda:

import fcntl, sys
pid_file = 'program.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    sys.exit(0)

Много как предложение S.Lott, но с кодом.

37
ответ дан Community 24 November 2019 в 02:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: