Python的Web浏览器在Windows相对路径上启动IE而不是默认浏览器

41

我试图从Python中使用默认浏览器打开本地HTML文件(如果我双击一个.html文件,我的默认浏览器是Google Chrome)

但是当我使用Python的webbrowser.open()时,IE浏览器被打开,且地址栏为空。

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

我已经检查了我的默认程序,它们看起来是正确的。我使用的是Win 7 SP1。为什么Chrome无法启动?

更新:代码将在未知的操作系统和计算机上运行,因此硬编码或注册浏览器或路径更新都不是选项。我认为解析url中的file://,然后进行os.path.exists检查和os.path.realpath可能是答案。


Shadikka查看源代码,我引用文档,Acorn在代码中提供了实用的建议。总体而言,它们是一个非常完整的答案。 - Steven Rumbalski
1
虽然如果有人知道如何使用webbrowser.registerBROWSER环境变量,那将是很好的信息。文档没有详细介绍。 - Acorn
3
看起来'file://'与相对路径的结合导致了问题。如果我去掉'file://'或使用os.path.realpath(filename),它就能正常工作并启动Google。我仍然想知道为什么一个错误的文件URL会回退到一个空地址栏的IE。 - McLeopold
McLeopold: 因为 Windows 基于扩展名来决定打开哪个浏览器(而我忘记了它对于目录、空或无效路径的默认行为是什么)。你可以将 Chrome 设置为 Windows 的默认浏览器,但仍然将 IE 作为关联 .MP3、.GIF 等扩展名的应用程序(或者实际上是 RealPlayer 或任何其他二进制文件)。请在您的问题中编辑这些详细信息。您是否只想保证 Windows 打开某种类型的扩展名时使用 Chrome? - smci
14个回答

29

我的主要问题是在尝试给相对路径添加 file:// 时出现了错误的URL。可以通过以下方法修复:

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

webbrowser.open方法会尝试多种方法,直到其中一种“成功”,这是一个宽松的定义。

WindowsDefault类调用os.startfile()失败并返回False。我可以通过在Windows运行命令中输入URL并查看错误消息而验证该信息。

无论URL是否正确,GenericBrowserBackgroundBrowser都将使用exe调用subprocess.Popen(),并且成功时将返回True。IE没有显示问题的迹象,所有其他浏览器都会显示一个好看的消息,说明它们找不到文件。

  1. GenericBrowser由环境变量BROWSER设置,并且排在第一位。
  2. WindowsDefault排在第二位。
  3. BackgroundBrowser排在最后,并包括备用的IE(如果其他方法均未起作用)。

以下是我的初始设置:

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

修改环境变量后,这是我的设置:

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

webbrowser._tryorder给出了尝试的浏览器列表。注册Chrome或添加BROWSER环境变量或修改路径都可以让我获得正确的浏览器和更好的错误提示信息。

谢谢大家的帮助,没有你们的想法我无法解决这个问题。


我不需要添加 file:// 或者使用 os.path.realpath(),甚至我的路径中有 ..!一旦我正确获取了文件路径,它就在我的默认浏览器(Chrome)中打开了,但是当我路径错误(例如忘记了 ..)时,它会默认使用IE。而且,无论是 / 还是 \ 都没有关系! - Mark Mikofski
你甚至不需要将 Chrome 设置为你的浏览器。只要它是默认浏览器,并且你的路径被包含在 os.path.realpath(path) 中,你就可以成功地在 Chrome 中启动。 - Yonatan Simson

16

您可以使用get(name)来选择特定的浏览器。

您需要注册 Chrome 浏览器,因为它似乎不是预定义的浏览器类型之一,然后您就可以执行以下操作:

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

更新:

实际上,您可能只需使用以下代码之一:

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

文档中没有Linux的预定义默认值。


11

这为我打开了一个新的Chrome标签页,并且它仍然与操作系统无关:

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

奇怪的是,即使没有get()调用,它仍然使用IE。这看起来像是一个有简单解决方法的错误。


3
你正在打开一个HTTP资源。问题是关于打开文件资源的,我认为这种区别很重要。 - Peter Graham
1
谢谢您先生!这实际上是目前唯一有效的解决方案!正如McLeopold所指出的,其他浏览器可能存在实际错误?.. - ewerybody
1
@PeterGraham 这个答案适用于任何协议,包括 file:// - Joe

5
在 Windows 10 上,简而言之,所有不包含完整 URL(例如 https://example.com)的内容都会在 IE 中打开。例如,如果我输入:
webbrowser.open("https://www.example.com")

它将在Chrome中打开一个新的选项卡,同时

webbrowser.open("example.com")

将打开IE浏览器。任何.get()都会导致它根本不打开浏览器。

这种行为有点奇怪,但我可以看出这是一个复杂的实现过程,很可能是操作系统导致了这种行为。


1
我认为不是操作系统的问题。我在 macOS 中遇到了同样的问题。不使用完整的 URL 导致网站在 Firefox 中被打开,而我的默认浏览器是 Safari。 - xilopaint

2
webbrowser 模块应该使用默认浏览器,所以这可能是一个 bug。另一方面,请使用 文档 中的这个解释来解决您的问题:

如果存在环境变量 BROWSER,则将其解释为要按顺序尝试的浏览器的 os.pathsep 分隔列表,覆盖平台默认浏览器列表。当列表部分的值包含字符串 %s 时,它被解释为文字浏览器命令行,用参数 URL 替换 %s;如果该部分不包含 %s,则仅将其解释为要启动的浏览器的名称。


1

看了一下模块源代码,它首先尝试使用Windows默认浏览器,但如果不行,它会搜索常见的浏览器名称作为命令,即在PATH变量中。尝试将您的Web浏览器位置添加到您的PATH。


1

我在使用Firefox时遇到了同样的问题。http://www.google.com 在Firefox中打开,而file:///test.html在IE中打开。

webbrowser doc说:

请注意,在某些平台上,尝试使用此函数打开文件名可能会起作用并启动操作系统关联的程序。但是,这既不受支持也不可移植。


1

对于我来说,在Python 3.6和Windows 10上,使用register()函数和BackgroundBrowser可以登录我想要的浏览器:

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

额外观察 -

webbrowser还有一个GenericBrowser类。

查看源代码,似乎BackgroundBrowser在调用subprocess.Popen()时使用了start_new_session,而GenericBrowser没有。

我不知道那个标志的确切功能。

然而,实际上,使用BackgroundBrowser会切换到浏览器窗口,而GenericBrowser只是打开标签页,但不会切换。


0

看起来 webbrowser 模块无法在当前工作目录中找到文件名,因为您通过快捷方式或终端打开程序,所以 cwd 与程序的目录不同。

在这种情况下,当给 webbrowser.open 函数提供路径时,您必须将路径转换为程序目录的绝对路径。

程序路径存储在全局常量 __file__ 中。

您可以像这样修复:

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

我通过这个解决方案解决了同样的问题。


0

我刚遇到了同样的问题,网页突然在Internet Explorer中打开,这只发生在安装Visual Studio 2017之后。我猜测VS2017安装了自己的IE版本。 我的程序使用webbrowser.open(url)打开网站,但我已经从每个URL的开头剥离了“https://”协议。现在,通过确保所有URL在开头都有“https://”协议,问题消失了,页面再次在Chrome(我的Windows默认浏览器)中打开。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接