В python, как мне запустить процесс, а затем выйти из моей текущей программы?

#python #subprocess #popen

Вопрос:

Предположим, у меня есть исполняемый файл A, который проверяет, можно ли его обновить при запуске. Если его можно обновить, я хотел бы, чтобы исполняемый файл B («updater.exe») для запуска и выполнения обновлений, но для того, чтобы программа обновления B функционировала, мне нужно, чтобы A вышел.

Я попробовал этот код, но A остается открытым, пока работает B, и это приводит к ошибкам:

 subprocess.Popen("start cmd /C updater.exe", shell=True, stdin=None, stdout=None, stderr=None, close_fds=True, creationflags=subprocess.DETACHED_PROCESS)
exit(0)
 

Примечание: это для программы, которая в основном используется в Windows 10, если это имеет значение.

Ответ №1:

Я не понимаю, почему ваш скрипт на python должен был бы завершиться для updater.exe для запуска, но если предположить, что существует какое-то взаимодействие между A и вещью, которую обновляет B, скажем, D, я бы предложил что-то вроде этого:

Один из вариантов:

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

Другой вариант:

Напишите сценарий C «сторожевого пса», который периодически запускает сценарий A (например, с помощью планировщика задач Windows). Затем скрипт A возвращает свой код выхода в скрипт C, который сообщает , можно ли выполнить обновление, например subprocess.check_output() , с помощью запущенного сценария A, и сценарий B может быть запущен, если C необходимо обновить D.

 # script C
import subprocess
from time import sleep 
# ^^ time.sleep may be a bit of a blunt hammer for this purpose;
# there are libraries which allow more advanced control/scheduling
# (like the stdlib's 'sched', or one could use windows task Scheduler. 
# On UNIX you could use CRON jobs, but on UNIX OSes one probably 
# wouldn't have this problem in the first place.


update_check_interval: int = 86400
watchdog_path = Path("C:/full/path/to/scriptB.py")
updater_path = Path("C:/full/path/to/updater.exe")

exit_codes_can_update = {
    1: True,
    0: False,
}
# ^^ This seems superfluous, but it could be confusing that usually 
# processes return 0 if successful, which in this case means
# 'not-updateable', or the other way around depending
# on what you make script A return.

while True:

    status = subprocess.check_output(
                 ['python',
                  f'{"str(watchdog_path)"}'])

    if exit_codes_can_update[status]:

        subprocess.call(
            ['start',
             f'"{updater_path}"'],
             stdin=None,
             stdout=None,
             stderr=None,
             creationflags=subprocess.DETACHED_PROCESS) 

    # ^^ double quotes w/ f-strings in the paths are there
    # case there are spaces in the path, although I am quite
    # uncertain that this is necessary.

    sleep(update_check_interval)

 

Я не думаю, что вам нужен этот shell=True параметр.

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