我需要能够使用Windows和Mac OS中的默认应用程序打开文档.基本上,我想做同样的事情,当你在资源管理器或Finder中双击文档图标时发生的事情.在Python中执行此操作的最佳方法是什么?
使用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
它是Free Desktop Foundation标准,适用于Linux桌面环境.
在Mac OS中,您可以使用"打开"命令.有一个类似的Windows API调用,但我不记得它.
好的,"start"命令会这样做,所以这应该有效.
Mac OS/X:
subprocess.check_call(['open', filename])
视窗:
subprocess.run(['open', filename], check=True)
好吧,显然这个愚蠢的争议还在继续,所以让我们看看用子进程做这件事.
open
并且start
分别是Mac OS/X和Windows的命令解释器.现在,假设我们使用子进程.通常,你会使用:
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
现在,这有什么好处?从理论上讲,这更安全 - 但实际上我们需要以某种方式执行命令行; 在任何一种环境中,我们都需要环境和服务来实现interpet,获取路径等等.在任何一种情况下我们都不执行任意文本,因此它没有固有的"但你可以输入subprocess
"问题,如果文件名可能被破坏,使用就os.system()
没有保护.
它实际上并没有给我们任何更多的错误检测,我们仍然依赖os.system
于任何一种情况.我们不需要等待子进程,因为我们是通过问题声明开始一个单独的进程.
"但是os.system
首选." 但是,A:\abc\def\a.txt
不会弃用,它是这项特定工作的最简单工具.
结论:使用shlex.quote
是最简单,最直接的方法,因此是正确的答案.
我更喜欢:
os.startfile(path, 'open')
请注意,此模块支持在其文件夹和文件中包含空格的文件名,例如
A:\abc\folder with spaces\file with-spaces.txt
(python docs)'open'不必添加(这是默认值).文档特别提到这就像在Windows资源管理器中双击文件的图标一样.
此解决方案仅限Windows.
仅仅为了完整性(它不在问题中),xdg-open将在Linux上做同样的事情.
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])
如果必须使用启发式方法,您可以考虑webbrowser
.
它是标准库,尽管它的名称,它也会尝试打开文件:
请注意,在某些平台上,尝试使用此函数打开文件名可能会起作用并启动操作系统的关联程序.但是,既不支持也不便携.(参考)
我尝试了这个代码,它在Windows 7和Ubuntu Natty中运行良好:
import webbrowser webbrowser.open("path_to_file")
此代码也可以在Windows XP Professional中使用Internet Explorer 8正常工作.
如果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.3兼容路径。
import subprocess import win32api filename = "C:\\Documents and Settings\\user\\Desktop\file.avi" filename_short = win32api.GetShortPathName(filename) subprocess.Popen('start ' + filename_short, shell=True )
该文件必须存在才能与API调用一起使用。