Как не запускать исполняемый файл python, если он уже существует в диспетчере задач

#python

#python

Вопрос:

Если у меня есть исполняемый файл python, скомпилированный в exe, как я могу проверить, запущен ли он уже в диспетчере задач, и если да, не запускать его новый экземпляр?

 import wmi
if (c.Win32_Process(name="Script.exe")):
    sys.exit()
else:
    #script.exe's code

  

Приведенный выше код использует модуль wmi, чтобы проверить, запущена ли программа, а затем остановить запуск нового экземпляра. Проблема в том, что скрипт никогда не будет запущен. Это связано с тем, что при script.exe если он запускается в первый раз, он сразу же появляется в диспетчере задач. Модуль WMI обнаруживает это и закрывает его, как только он открывается. Я подтвердил это, переименовав исполняемый файл в Script2.exe , который запускает программу просто отлично.

Есть ли какой-либо способ правильно проверить, запущен ли исполняемый файл python?

Ответ №1:

Если файл не удаляется при завершении работы системы, вы можете попробовать это:

Создайте папку temp .txt в любом месте вашей системы, затем запретите доступ к ней любым другим программам, заставив python думать, что она «в настоящее время используется другой программой». Например:

 import threading
import os

pth = os.getcwd()   '\text.txt'

if os.path.exists(pth):
    try:
        os.remove(pth)
    except PermissionError:
        sys.exit()
else:
    open(pth,"w ").close()

f = open(pth,"w ")
def loop():
    while True:
        pass
threading.Thread(target=loop).start()
  

Если будет запущен другой экземпляр программы, вы получите PermissionError и программа закроется.

Комментарии:

1. Аккуратное решение. Просто обратите внимание, что это работает только в Windows. И даже тогда он может также сломаться при странных обстоятельствах, например, если файл блокировки хранится в общей сетевой папке, как бы маловероятно это ни было.

Ответ №2:

Одним из общих методов для этого является блокировка файлов. Иногда также называемые файлами pid.

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

 import os
LOCK_FILE = "C:\Path\To\myapplication.lock"

if os.path.exists(LOCK_FILE):
    print(f"LOCK FILE {LOCK_FILE} already exits. Exiting")
    sys.exit(1)
else:
    with open(LOCK_FILE, 'w') as f:
        f.write(f'{os.getpid()}')

try:
    main()
finally:
    try:
        os.remove(LOCK_FILE)
    except OSError:
        pass

  

Можно было бы улучшить обработку, но это основная идея.

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

Не идеально, но вы также можете улучшить свое решение, проверив текущее pid значение и название программы.

 for process in processes:
    if process.pid != os.getpid() and process.name == script_name:
        sys.exit(1)
  

Одна из причин, по которой это не идеально, заключается в том, что имя исполняемого файла не гарантируется (как вы отметили, имя файла может быть просто изменено, и это прерывается)

Комментарии:

1. Это решение идеально подходит для большинства скриптов на Python. Однако мой скрипт должен постоянно выполняться в фоновом режиме. Поскольку у процесса нет реального «конца», когда файл блокировки удаляется, процесс продолжается. Это позволяет вызывать его снова, пока предыдущая версия все еще запущена.

2. Это решение все еще работает в этом случае. when the lock file is removed Файл блокировки не будет удален сам по себе. Единственный случай, когда его следует удалить, — это когда программа останавливается. Если программа никогда не останавливается ( main() выполняется вечно), файл никогда не будет удален. finally: Предложение предназначено для ситуаций, например, если система завершает работу. Python попытается очистить файл перед выключением системы, поэтому процесс может начаться при запуске процесса после восстановления системы.

3. На самом деле я не продумал все до конца — это действительно работает!

4. Рад, что это работает для вас. Я также добавил пару альтернатив, а также пищу для размышлений 🙂

Ответ №3:

is_process_exists возвращает True , если процесс существует, False если нет:

 import psutil

def is_process_exists(process_name):
    return bool([p for p in psutil.process_iter() if psutil.Process(p.pid).name() == process_name])
  

Комментарии:

1. Я думаю, что проблема в этом случае заключается в том, что сам скрипт пытается проверить, запущен ли процесс… но, конечно, он всегда будет запущен, если программа проверяет свое собственное имя 🙂