процесс.функция terminate() не работает для подпроцесса chrome / firefox, если окно браузера уже присутствует
Я запускаю подпроцесс, используя следующую команду:
p=subprocess.Popen(["google-chrome","--new-window","http://www.hckrnews.com"])
Мне нужно убить этот процесс через некоторое время, поэтому я использую:
time.sleep(t)
p.terminate()
Это работает только в том случае, если ни один экземпляр браузера еще не открыт. Если окно браузера уже присутствует, новое окно открывается, но не завершается по истечении указанного времени.
Я также попробовал метод, приведенный в этом вопросе, но это также не работает в случае уже существующего окна.
2 ответа:
Это Не проблема python, и ваш код не содержит ошибок. Это проблема с браузерами. При запуске исполняемого файла firefox или chrome с помощью
Другими словами, процесс, который вы только что запустили, подключается к уже существующему процессу firefox/chrome и дает команду этому процессу открыть новое окно, а затем завершает работу. Поэтому, когда вы звоните--new-window
открывается новое окно в существующем экземпляре браузера.terminate()
, на самом деле ничего не происходит потому что процесс, который вы начали, уже закончился.Вы можете проверить это с помощью нескольких строк кода:
>>> import subprocess >>> p = subprocess.Popen(['firefox', '-new-window']) >>> p.wait() # uh-oh. this should be blocking! 0 >>> p.terminate() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/subprocess.py", line 1551, in terminate self.send_signal(signal.SIGTERM) File "/usr/lib/python2.7/subprocess.py", line 1546, in send_signal os.kill(self.pid, sig) OSError: [Errno 3] No such process
Вы должны сказать браузеру, чтобы он открыл новый экземпляр вместо нового окна. Firefox имеет опцию
-new-instance
, хотя, когда я пытаюсь ее использовать, единственное, что я получаю,-это всплывающее окно, в котором говорится, что я не могу открыть два экземпляра браузера. Разрешено ли открывать несколько экземпляров браузера в определенном сеансе ОС, зависит от браузера и может не быть возможно .В Chrome я полагаю, что вы можете открыть новый сеанс, в котором Chrome будет использовать другой каталог для хранения своих данных (см. здесь, например). Понятия не имею, возможно ли это в Firefox.
Как объяснено в ответе Бакуриу ,
--new-window
создает новое окно, но под существующим экземпляром firefox, если таковой имеется. Если не существует существующего экземпляра, создается новый.Можно использовать
-new-instance
, чтобы сказать Firefox, чтобы начать новый экземпляр для другой Профиль пользователя firefox. Профиль должен уже существовать, и это ограничено одним экземпляром на профиль. Новый профиль можно создать интерактивно с помощьюfirefox -P -new-instance
, а затем запустить новый экземпляр сfirefox -P <profile_name> -new-instance
. Документация профиля Mozilla находится здесь.Должно быть возможно программно создать профиль - ведь это всего лишь каталог и запись в файле
~/.mozilla/profiles.ini
. Конечно, это только для Firefox, chrome может быть совершенно другим (или невозможным?). Пример:import tempfile import subprocess import shutil import time import ConfigParser MOZILLA_PROFILES_INI = '.mozilla/firefox/profiles.ini' PROFILE_SECTION = 'Profile1' URL = 'http://www.hckrnews.com' profile_dir = tempfile.mkdtemp() # quick and dirty add new profile to profiles.ini, or update if already present. config = ConfigParser.SafeConfigParser() config.optionxform = str # preserve case of option names config.read(MOZILLA_PROFILES_INI) try: config.add_section(PROFILE_SECTION) except ConfigParser.DuplicateSectionError, exc: pass config.set(PROFILE_SECTION, 'Name', 'temp_profile') config.set(PROFILE_SECTION, 'IsRelative', '0') config.set(PROFILE_SECTION, 'Path', profile_dir) # write out config with hack to remove added spaces around '=' - more care needed here as it just overwrites the global mozilla config! class NoSpaceWriter(file): def write(self, s): super(NoSpaceWriter, self).write(s.replace(' = ', '=')) with NoSpaceWriter(MOZILLA_PROFILES_INI, 'w') as profiles_ini: config.write(profiles_ini) p = subprocess.Popen(['firefox', '-P', 'temp_profile', '-new-instance', URL]) time.sleep(10) p.terminate() shutil.rmtree(profile_dir, True)