#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 прямо сейчас. Кроме того, я сомневаюсь, что это предпочтительный способ сделать это, но это может дать вам один возможный подход.