2014-09-01 3 views
3

Я запускает подпроцесс с помощью следующей команды:process.terminate() не работает хром/FireFox подпроцесса, если окно браузера уже присутствует

p=subprocess.Popen(["google-chrome","--new-window","http://www.hckrnews.com"]) 

Мне нужно, чтобы убить этот процесс после чего я использую:

time.sleep(t) 
p.terminate() 

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

Я также пробовал метод, указанный в этом question, но это также не работает в случае уже существующего окна.

ответ

5

Это не проблема с python, и ваш код не содержит ошибок. Это проблема с браузерами. При запуске исполняемого файла firefox или chrome с --new-window открывается новое окно в существующем экземпляре.

Другими словами, процесс, который вы только что начали, подключается к уже существующему процессу firefox/chrome и инструктирует , что процесс открывает новое окно, а затем завершается. Поэтому, когда вы вызываете 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 использовать другой каталог для хранения своих данных (см., Например, here). Не знаю, возможно ли это в firefox.

+0

Большое спасибо! Я попробую использовать Chrome с другим каталогом для пользовательских данных. Кроме того, не имеет смысла, что Firefox имеет параметр -new-instance, но не позволяет открывать несколько экземпляров! – metanoia

+1

@quasistatic: допускаются множественные экземпляры, просто они должны использовать разные профили. – mhawke

3

Как объясняется в Bakuriu's answer, --new-window создает новое окно, но под существующим экземпляром firefox, если таковой имеется. Если существующего экземпляра нет, создается новый.

Можно использовать -new-instance, чтобы сообщить Firefox о начале нового экземпляра для разных пользователей. Профиль пользователя firefox. Профиль должен уже существовать, и это ограничивается одним экземпляром для каждого профиля. Новый профиль может быть создан в интерактивном режиме с помощью firefox -P -new-instance, а затем можно запустить новый экземпляр с firefox -P <profile_name> -new-instance. Документация профиля Mozilla: here.

Должно быть возможным программное создание профиля - ведь это всего лишь каталог и запись в файле ~/.mozilla/profiles.ini. Конечно, это только для Firefox, хром может быть совершенно другим (или невозможным?). Пример:

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)