我需要能够使用Windows和Mac OS中的默认应用程序打开文档。基本上,我想做的事情与您在资源管理器或Finder中双击文档图标时发生的事情相同。用Python做到这一点的最佳方法是什么?
我需要能够使用Windows和Mac OS中的默认应用程序打开文档。基本上,我想做的事情与您在资源管理器或Finder中双击文档图标时发生的事情相同。用Python做到这一点的最佳方法是什么?
Answers:
open
和start
分别是Mac OS / X和Windows的命令解释器。
要从Python调用它们,可以使用subprocess
module或os.system()
。
以下是有关使用哪个软件包的注意事项:
您可以通过致电给他们os.system
,该电话有效,但是...
转义: os.system
仅适用于路径名中没有空格或其他shell元字符的文件名(例如A:\abc\def\a.txt
),否则需要转义。有shlex.quote
针对Unix的系统,但没有Windows的真正标准。也许还会看到python,windows:用shlex解析命令行
os.system("open " + shlex.quote(filename))
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()
因此使用也是正确的答案。
明显的缺点是Windows start
命令要求您传递shell=True
,否定了使用的大多数好处subprocess
。
filename
形式的不同,这是为何os.system()不安全和糟糕的完美示例。子过程更好。
os.system()
在于它使用外壳程序(并且您在这里没有进行任何外壳程序转义,因此对于恰好包含外壳程序元字符的完全有效的文件名,将发生“坏事”)。subprocess.call()
首选之所以是您可以选择使用绕过Shell subprocess.call(["open", filename])
。这适用于所有有效的文件名,即使对于不受信任的文件名也不会引入shell注入漏洞。
使用subprocess
Python 2.4+上可用的模块,而不要使用os.system()
,因此您不必处理外壳转义。
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桌面环境中使用。
xdg-open
- linux.die.net/man/1/xdg-open
xdg-open test.py
,它为我打开了Firefox下载对话框。怎么了?我正在使用manjaro linux。
xdg-open
配置很混乱,但这并不是我们可以在注释中解决的问题。也许请看unix.stackexchange.com/questions/36380/…–
我更喜欢:
os.startfile(path, 'open')
请注意,此模块支持在其文件夹和文件中带有空格的文件名,例如
A:\abc\folder with spaces\file with-spaces.txt
(python docs)不必添加'open'(这是默认值)。文档特别提到这就像双击Windows资源管理器中的文件图标。
此解决方案仅适用于Windows。
startfile
功能甚至不存在,而不是引发错误,这意味着用户将收到有关缺少功能的令人困惑的错误消息。您可能要检查平台以避免这种情况。
仅出于完整性考虑(这不是问题),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")
使用Internet Explorer 8,此代码在Windows XP Professional中也可以正常工作。
import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
如果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调用一起使用。
start "Title" "C:\long path to\file.avi"
我已经很晚了,但是这里是使用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文档以获取更多信息。
os.startfile(file)
呢?
如果要指定用于在Mac OS X上打开文件的应用程序,请使用以下命令:
os.system("open -a [app name] [file name]")
在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))