如果已存在浏览器窗口,则process.terminate()不适用于chrome / firefox子进程

时间:2014-09-01 12:26:18

标签: python subprocess kill-process

我正在使用以下命令启动子进程:

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

我需要在一段时间后终止这个过程,所以我正在使用:

time.sleep(t)
p.terminate()

仅当浏览器的实例尚未打开时才有效。如果已存在浏览器窗口,则会打开一个新窗口,但不会在指定时间后终止。

我也尝试了这个question中给出的方法,但是在已经存在的窗口的情况下也没有用。

2 个答案:

答案 0 :(得分:6)

这是一个python问题,而且您的代码不包含错误。这是浏览器的问题。当您使用--new-window启动firefox或chrome的可执行文件时,将在浏览器的现有实例中打开一个新窗口。

换句话说,刚刚开始的进程连接到现有的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选项,即使在尝试使用它时,我唯一得到的是弹出窗口显示我无法打开浏览器的两个实例。是否允许在某个OS会话中打开多个浏览器实例取决于浏览器,可能无法实现

在Chrome上我相信您可以打开一个新会话,告诉Chrome使用其他目录存储其数据(例如,请参阅here)。不知道这是否可行  在Firefox中。

答案 1 :(得分: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,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)