Process.terminate () does not work for chrome / firefox subprocess if browser window is already present

I start a subprocess using the following command:

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

      

I need to kill this process after a while, so I use:

time.sleep(t)
p.terminate()

      

This only works if no instance of the browser is already open. If a browser window is already present, a new window opens, but does not end after the specified time.

I also tried the method given in this question , but that also doesn't work in the case of an already existing window.

+3


source to share


2 answers


This is not a python problem and your code is error free. This is a problem with browsers. When you launch the firefox or chrome executable with --new-window

, a new window opens in your existing browser instance .

In other words, the process you just started attaches to an already existing firefox / chrome process and indicates that the process will open a new window and then exit. So when you call terminate()

, nothing happens because the process you started has already ended.

You can check this with a few lines of code:



>>> 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

      

You have to tell the browser to open a new instance instead of a new window. Firefox has an option -new-instance

, although when trying to use it, the only thing I get is a popup that says I can't open two instances of the browser. Whether it is possible to open multiple instances of the browser in a particular OS session is browser dependent and may not be possible.

In Chrome, I believe you can open a new session that says Chrome is using a different directory to store its data (like the one here ). Don't know if this is possible in firefox.

+5


source


As explained in Bakuriu's answer , --new-window

creates a new window, but underneath the existing firefox instance, if one exists. If there is no existing instance, a new one is created.

Can be used -new-instance

to tell Firefox to start a new instance for a different firefox user profile. The profile must already exist and this is limited to one instance per profile. You can create a new profile interactively with firefox -P -new-instance

, and then firefox -P <profile_name> -new-instance

you can start a new instance with. The Mozilla Profile Documentation is here .



It should be possible to programmatically create a profile - it's just a directory and a file entry ~/.mozilla/profiles.ini

. Of course this is only for Firefox, chrome might be completely different (or impossible?). Example:

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)

      

+3


source







All Articles