在 Windows 和 Mac OS 中使用 Python 中的默认操作系统应用程序打开文档
- 2024-12-19 09:24:00
- admin 原创
- 111
问题描述:
我需要能够使用 Windows 和 Mac OS 中的默认应用程序打开文档。基本上,我想执行与双击 Explorer 或 Finder 中的文档图标时相同的操作。在 Python 中执行此操作的最佳方法是什么?
解决方案 1:
使用subprocess
Python 2.4+ 上可用的模块,而不是os.system()
,这样您就不必处理 shell 转义。
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', filepath))
elif platform.system() == 'Windows': # Windows
os.startfile(filepath)
else: # linux variants
subprocess.call(('xdg-open', filepath))
双括号是因为subprocess.call()
需要将序列作为其第一个参数,因此我们在这里使用元组。在带有 Gnome 的 Linux 系统上,还有一个gnome-open
命令可以执行相同的操作,但xdg-open
它是自由桌面基金会标准,并且可以在 Linux 桌面环境中使用。
解决方案 2:
open
和start
分别是 Mac OS/X 和 Windows 的命令解释器,用于执行此操作。
要从 Python 调用它们,您可以使用subprocess
模块或os.system()
。
关于使用哪个包,请考虑以下事项:
您可以通过 调用它们
os.system
,这可行,但是......
转义: os.system
仅适用于路径名中没有任何空格或其他 shell 元字符的文件名(例如A:abcdefa.txt
),否则需要对其进行转义。Unixshlex.quote
类系统有转义,但 Windows 并没有真正的标准。也许还可以参见python、windows:使用 shlex 解析命令行
* MacOS / X:`os.system("open " + shlex.quote(filename))`
* Windows:`os.system("start " + filename)`严格来说`filename`也应该进行转义。
subprocess
您也可以通过模块调用它们,但是......
对于 Python 2.7 及更新版本,只需使用
subprocess.check_call(['open', filename])
在 Python 3.5+ 中,你可以等效地使用稍微复杂但也更通用的
subprocess.run(['open', filename], check=True)
如果您需要一直兼容到 Python 2.4,您可以使用subprocess.call()
并实现您自己的错误检查:
try:
retcode = subprocess.call("open " + filename, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError, e:
print >>sys.stderr, "Execution failed:", e
现在,使用有什么好处subprocess
?
* **安全性:**理论上,这更安全,但实际上我们需要以某种方式执行命令行;在任一环境中,我们都需要环境和服务来解释、获取路径等。在这两种情况下,我们都不会执行任意文本,因此它不存在固有的“但您可以输入`'filename ; rm -rf /'`”问题,并且**如果**文件名可能被破坏,则使用`subprocess.call`不会给我们带来额外的保护。
* **错误处理:**它实际上并没有为我们提供任何错误检测,`retcode`在任何一种情况下我们仍然依赖于;但是在发生错误时明确引发异常的行为肯定会帮助您注意到是否存在故障(尽管在某些情况下,回溯可能并不比简单地忽略错误更有帮助)。
* **生成一个(非阻塞)子进程**:我们不需要等待子进程,因为我们通过问题陈述启动一个单独的进程。对于反对意见“但`subprocess`更可取”。然而,`os.system()`并没有被弃用,从某种意义上说,它是这项特定工作最简单的工具。结论:`os.system()`因此使用也是一个正确的答案。
一个明显的缺点是 Windowsstart
命令要求您传入,shell=True
这抵消了使用的大部分好处subprocess
。
解决方案 3:
我更喜欢:
os.startfile(path, 'open')
请注意,此模块支持文件夹和文件中带有空格的文件名,例如
A:abcolder with spacesile with-spaces.txt
( python 文档) 无需添加“open”(这是默认设置)。文档特别提到,这就像在 Windows 资源管理器中双击文件图标一样。
此解决方案仅适用于 Windows。
解决方案 4:
只是为了完整性(它不在问题中),xdg-open将在 Linux 上执行相同的操作。
解决方案 5:
import os
import subprocess
def click_on_file(filename):
'''Open document with default application in Python.'''
try:
os.startfile(filename)
except AttributeError:
subprocess.call(['open', filename])
解决方案 6:
如果你必须使用启发式方法,你可以考虑webbrowser
。
它是标准库,尽管它的名字如此,它也会尝试打开文件:
请注意,在某些平台上,尝试使用此函数打开文件名可能会起作用并启动操作系统的关联程序。但是,这既不受支持也不可移植。(参考)
我尝试了此代码并且它在 Windows 7 和 Ubuntu Natty 中运行良好:
import webbrowser
webbrowser.open("path_to_file")
此代码在 Windows XP Professional 中使用 Internet Explorer 8 也能正常运行。
解决方案 7:
如果你想按照这种subprocess.call()
方式操作,在 Windows 上它应该是这样的:
import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))
你不能只使用:
subprocess.call(('start', FILE_NAME))
因为start
不是可执行文件,而是程序的命令cmd.exe
。以下代码有效:
subprocess.call(('cmd', '/C', 'start', FILE_NAME))
但前提是 FILE_NAME 中没有空格。
虽然subprocess.call
方法en正确地引用了参数,但是该start
命令的语法相当奇怪,其中:
start notes.txt
除以下之外还做了其他事情:
start "notes.txt"
第一个带引号的字符串应该设置窗口的标题。为了使其与空格兼容,我们必须这样做:
start "" "my notes.txt"
这就是上面的代码所做的事情。
解决方案 8:
Start 不支持长路径名和空格。您必须将其转换为兼容 8.3 的路径。
import subprocess
import win32api
filename = "C:\\Documents and Settings\/user\\Desktopile.avi"
filename_short = win32api.GetShortPathName(filename)
subprocess.Popen('start ' + filename_short, shell=True )
该文件必须存在才能与 API 调用一起工作。
解决方案 9:
os.startfile(path, 'open')
在 Windows 下是好的,因为当目录中存在空格时,os.system('start', path_name)
无法正确打开应用程序,并且当目录中存在 i18n 时,os.system
需要将 unicode 更改为 Windows 中控制台的编解码器。
解决方案 10:
以下是 Nick 的回答,针对 WSL 稍作了调整:
import os
import sys
import logging
import subprocess
def get_platform():
if sys.platform == 'linux':
try:
proc_version = open('/proc/version').read()
if 'Microsoft' in proc_version:
return 'wsl'
except:
pass
return sys.platform
def open_with_default_app(filename):
platform = get_platform()
if platform == 'darwin':
subprocess.call(('open', filename))
elif platform in ['win64', 'win32']:
os.startfile(filename.replace('/','\\'))
elif platform == 'wsl':
subprocess.call('cmd.exe /C start'.split() + [filename])
else: # linux variants
subprocess.call(('xdg-open', filename))
解决方案 11:
我来晚了,但这里有一个使用 windows api 的解决方案。这总是打开关联的应用程序。
import ctypes
shell32 = ctypes.windll.shell32
file = 'somedocument.doc'
shell32.ShellExecuteA(0,"open",file,0,0,5)
很多魔法常数。第一个零是当前程序的 hwnd。可以为零。其他两个零是可选参数(参数和目录)。5 == SW_SHOW,它指定如何执行应用程序。阅读
ShellExecute API 文档了解更多信息。
解决方案 12:
如果您想指定在 Mac OS X 上打开文件的应用程序,请使用以下命令:os.system("open -a [app name] [file name]")
解决方案 13:
在 Windows 8.1 上,下面的方法可以工作,但其他给出的方法subprocess.call
由于路径中有空格而失败。
subprocess.call('cmd /c start "" "any file path with spaces"')
通过利用这个和其他人的答案,这里有一个可以在多个平台上运行的内联代码。
import sys, os, subprocess
subprocess.call(('cmd /c start "" "'+ filepath +'"') if os.name is 'nt' else ('open' if sys.platform.startswith('darwin') else 'xdg-open', filepath))
解决方案 14:
在 mac os 上你可以调用open
:
import os
os.open("open myfile.txt")
这将使用 TextEdit 或为此文件类型设置为默认的任何应用程序打开该文件。
解决方案 15:
我建立了一个小型库,结合了这里最好的答案来实现跨平台支持:
$ pip install universal-startfile
然后启动一个文件或者 URL:
from startfile import startfile
startfile("~/Downloads/example.png")
startfile("http://example.com")
解决方案 16:
我想您可能想在编辑器中打开文件。
对于 Windows
subprocess.Popen(["notepad", filename])
对于 Linux
subprocess.Popen(["text-editor", filename])
解决方案 17:
调用 open file() 函数时出现错误。我按照指南操作,但指南是在 Windows 中编写的,而我在 Linux 上。因此 os.statrfile 方法对我不起作用。我可以通过执行以下操作来缓解此问题:
导入库
import sys, os, subprocess
import tkinter
import tkinter.filedioalog as fd
import tkinter.messagebox as mb
导入库之后,我调用子进程方法在基于 unix 的操作系统中打开文件,即“xdg-open”和将要打开的文件。
def open_file():
file = fd.askopenfilename(title='Choose a file of any type', filetypes=[('All files', "*.*")])
subprocess.call(['xdg-open', file])
解决方案 18:
现在,这就像安装shopen并执行一样简单
import shopen
shopen.open(filepath)
欢迎反馈!
shutil.open
值得一提的是,这可能最终会按照python/cpython#47427在标准库中实现,但那里的开发似乎在 2012 年停滞了。
与此同时,最好的选择仍然是os.startfile
和特殊情况subprocess
调用的组合,正如最高投票答案https://stackoverflow.com/a/435669所建议的那样。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)