python's webbrowser launches IE, instead of default browser, on Windows relative path
Asked Answered
E

14

41

I'm attempting to launch a local html file from python in the default browser (right now my default is Google Chrome if I double-click on a .html file, Chrome launches.)

When I use python's webbrowser.open(), IE launches instead, with a blank address bar.

Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import webbrowser
>>> filename = 'test.html'
>>> webbrowser.open('file://'+filename)
True
>>> print(webbrowser.get().__class__.__name__)
WindowsDefault

I've checked my default programs and they look correct. I'm on Win 7 SP1. Why is Chrome not launching?

Update: The code will be running on unknown OS's and machines, so hardcoding or registering browsers or path updates are not options. I'm thinking that parsing the url for file:// and then doing an os.path.exists check and os.path.realpath might be the answer.

Engraving answered 6/5, 2011 at 19:43 Comment(4)
Shadikka looks at the source code, I quote the docs, and Acorn gives a practical suggestion in code. Altogether they are a very complete answer.Brenan
Although if someone knows how to use webbrowser.register and the BROWSER environment variable it would be good information to have. The docs don't go into much detail.Lowder
It looks like the 'file://' in combination with a relative path is causing the issue. If I drop the 'file://' or use os.path.realpath(filename) it works, and google launches. I'm still wondering why a bad file url would then fall back to IE with a blank address bar.Engraving
McLeopold: because Windows decides which browser to open on a per-extension basis (and I forget what its default behavior is for directories, let alone empty or invalid paths). You could have Chrome as the Windows default browser, but still IE as the application associated with .MP3, .GIF extensions etc. (or indeed RealPlayer or any other binary). Please edit those details into your question. Do you only want to guarantee Windows opens Chrome for a certain type of extension?Canty
E
29

My main issue was a bad URL by attempting prepend file:// to a relative path. It can be fixed with this:

webbrowser.open('file://' + os.path.realpath(filename))

Using webbrowser.open will try multiple methods until one "succeeds", which is a loose definition.

The WindowsDefault class calls os.startfile() which fails and returns False. I can verify that by entering the URL in the windows run command and seeing an error message rather than a browser.

Both GenericBrowser and BackgroundBrowser will call subprocess.Popen() with an exe which will succeed, even with a bad URL, and return True. IE gives no indication of the issue, all other browsers have a nice messages saying they can't find the file.

  1. GenericBrowser is set by the environment variable BROWSER and is first.
  2. WindowsDefault is second.
  3. BackgroundBrowser is last and includes the fall back IE if nothing else works.

Here is my original setup:

>>> import webbrowser
>>> webbrowser._tryorder
['windows-default',
 'C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE']
>>> webbrowser._browsers.items()
[('windows-default', [<class 'webbrowser.WindowsDefault'>, None]),
 ('c:\\program files\\internet explorer\\iexplore.exe', [None, <webbrowser.BackgroundBrowser object at 0x00000000022E3898>])]
>>>

Here is my setup after modifiying the environment variables:

C:>path=C:\Program Files (x86)\Mozilla Firefox;%path%

C:>set BROWSER=C:\Users\Scott\AppData\Local\Google\Chrome\Application\chrome.exe

C:>python
Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import webbrowser
>>> webbrowser._tryorder
['C:\\Users\\Scott\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe',
 'windows-default',
 'firefox',
 'C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE']
>>> webbrowser._browsers.items()
[('windows-default', [<class 'webbrowser.WindowsDefault'>, None]),
 ('c:\\program files\\internet explorer\\iexplore.exe',[None, <webbrowser.BackgroundBrowser object at 0x000000000235E828>]),
 ('firefox', [None, <webbrowser.BackgroundBrowser object at 0x000000000235E780>]),
 ('c:\\users\\scott\\appdata\\local\\google\\chrome\\application\\chrome.exe', [None, <webbrowser.GenericBrowser object at 0x000000000235E8D0>])]
>>>

The webbrowser._tryorder gives the list of browsers tried. Registering chrome or adding a BROWSER env var or modifiying my path all would have gotten me the correct browser with a better error message.

Thanks for the help guys, I couldn't have solved this without your ideas.

Engraving answered 9/5, 2011 at 23:50 Comment(2)
I didn't need to append file:// or use os.path.realpath() and I even had .. in my path! As soon as I got the filepath correct, it opened in my default browser (chrome), but when I had the wrong path (forgot the .. in my case) it defaulted to IE. And it didn't even matter if had partial paths with either / or \!Newfeld
You don't have to even set chrome as your browser. As long as it is the default browser and your path is wrapped in os.path.realpath(path) you will launch successfully in chromeContamination
L
16

You can use get(name) to use a specific browser.

You'll need to register the Chrome webbrowser, as it doesn't seem to be one of the predefined browser types, and then you should be able to do this:

webbrowser.get('chrome').open('http://www.google.com')

Update:

Actually, you might be able to just one of the following:

webbrowser.get('windows-default').open('http://www.google.com') webbrowser.get('macosx').open('http://www.google.com')

The docs show no predefined defaults for Linux.

Lowder answered 6/5, 2011 at 19:53 Comment(0)
M
11

This opened a new Chrome tab for me, and it's still OS-independent:

webbrowser.get().open('http://www.google.com')

What's odd is that without the get() call, it still uses IE. This looks like a bug with a simple workaround.

Mayhem answered 8/7, 2012 at 14:41 Comment(3)
You're opening an http resource. The question is about opening a file resource and the difference is important, I thinkPalmitin
THANK you Sir! This is actually the only working solution so far! As McLeopold was pointing out there might be an actual bug with the other browsers?..Depressed
@PeterGraham The answer works for any protocol, including file://.Mayhem
T
5

Using Windows 10, in short, everything that does not include a full URL in the https://example.com format is opened in IE for me. For example, if I say

webbrowser.open("https://www.example.com")

it will open a new tab in Chrome, while

webbrowser.open("example.com")

will open IE. Any .get() will cause it to not open a browser at all.

Kind of weird behaviour, but I can see that this is a complex thing do implement and likely the OS is to blame for this behavior.

Thermophone answered 18/3, 2017 at 10:56 Comment(1)
I think it's not OS's fault. I have the same issue in macOS. Not using the full URL causes the website being opened in Firefox meanwhile my default browser is Safari.Piggyback
B
2

The webbrowser module is supposed to use the default browser, so this might be a bug. On the other hand, use this explanation from the docs to troubleshoot your problem:

If the environment variable BROWSER exists, it is interpreted to override the platform default list of browsers, as a os.pathsep-separated list of browsers to try in order. When the value of a list part contains the string %s, then it is interpreted as a literal browser command line to be used with the argument URL substituted for %s; if the part does not contain %s, it is simply interpreted as the name of the browser to launch.

Brenan answered 6/5, 2011 at 19:54 Comment(0)
M
1

Looking at the module source code, it first tries to use the Windows default browser but if it doesn't work, it searches for common browser names that are commands, ie. that are in the PATH variable. Try adding the location of your web browser to your PATH.

Mantua answered 6/5, 2011 at 19:53 Comment(0)
S
1

I have the same problem with firefox. http://www.google.com is opened in ff while file:///test.html is opened in IE.

webbrowser doc says:

Note that on some platforms, trying to open a filename using this function, may work and start the operating system’s associated program. However, this is neither supported nor portable.

Sunderland answered 6/5, 2011 at 19:57 Comment(0)
P
1

What worked for me with Python 3.6, Windows 10, was using the register() function with BackgroundBrowser, to sign in my desired browser:

import webbrowser

# Register your preferable browser
browser_path = 'C:/path/to/opera.exe'
webbrowser.register('opera', None, webbrowser.BackgroundBrowser(browser_path))

# Get an instance and launch your file
browser = webbrowser.get('opera') 
browser.open('html_file')

Bonus observation -

webbrowser also has a GenericBrowser class.

Looking at the source, seems BackgroundBrowser uses start_new_session when calling subprocess.Popen(), whereas GenericBrowser does not.

I'm not aware of that flag's exact functionality.

Practically however, using BackgroundBrowser switches to the browser window, while GenericBrowser just opens the tab, but doesn't switch.

Predictory answered 24/5, 2019 at 20:54 Comment(0)
F
0

This problem appears for me only with file:/// protocol URLs, which are probably not registered to chrome, so os.startfile() (which is the first thing webbrowser.open tries on Windows) opens them in Internet Explorer. I don't think putting your other browser in the PATH will help, since os.startfile() still gets invoked before even trying the browsers in the path.

What you can do, is to check the default browser for http:// in the registry (for instance, by checking the registry key HKEY_CLASSES_ROOT\http\shell\open\command) and use that one for file:/// URLs. Not pretty, but it should work.

import _winreg
import webbrowser
import shlex
import subprocess

def win_browser_open(url):
    if url.startswith('file:///'):
        browser = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, r'http\shell\open\command')
        browser = browser.replace('%1', url)
        subprocess.Popen(shlex.split(browser))
    else:
        webbrowser.open(url)
Forget answered 6/5, 2011 at 20:6 Comment(0)
C
0

Use this:

import webbrowser
webbrowser.get('windows-default').open('http://www.google.com')
Cavalcade answered 21/3, 2020 at 23:28 Comment(0)
B
0

since all answers did not solve this/my issue, this way worked for me... (windows)

commands needs to be in a list, not in a single string! (in this case, "start", "filepath"), also shell needs to be True (windows)

import subprocess
subprocess.Popen(['start', 'C:/Users/User/Desktop/convert_report.html'], shell=True)
Barramunda answered 8/8, 2020 at 18:57 Comment(2)
Sorry, no. This is not a proper solution. You're only using subprocess.Popen(..., shell=True) to get the same system-path-resolving functionality you could get otherwise. You should just directly do what the webbrowser documentation tells you, like the other answers are telling you. Worse still, needlessly using subprocess.Popen() can open you up to command injection attacks. This answer is bad for many different reasons.Canty
Here's a fourth reason: just because a (Windows) user has a PATH envvar, doesn't mean it's non-empty and guaranteed to contain a valid path to Chrome, or to anything else. (This is common on new/unconfigured machines or VMs).Canty
F
0

It seems that webbrowser module couldn't find filename in cwd because you opened the program by shortcut or terminal, so cwd is different from the program's directory.

In that case, you have to convert the path into the absolute path of the program's directory when giving a path to webbrowser.open function.

The program's path is stored as __file__ global constant.

You can fix like that:

webbrowser.open(os.path.join(__file__, '..', filename))

I fixed the same problem by this solution.

Fons answered 24/8, 2021 at 16:32 Comment(0)
R
0

Add a BROWSER variable to your system variables and put path of your default browser.

Ries answered 13/12, 2021 at 13:1 Comment(0)
D
0

I just had the same issue of web pages suddenly opening with Internet Explorer, which only started after installing Visual Studio 2017. My guess is that VS2017 installed its own version of IE. My program was opening websites using webbrowser.open(url), but I had stripped the 'https://' protocol from the beginning of each URL. Now, by making sure that all URLs have the 'https://' protocol at the beginning, the issue goes away and the pages are once again opened in Chrome (my Windows default browser).

Daffi answered 31/10, 2022 at 0:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.