用Python中的默认应用程序打开文档
我需要能够使用Windows和Mac OS中的默认应用程序打开文档。 基本上,我想要做同样的事情,当你双击文件图标在资源pipe理器或Finder中发生。 什么是在Python中做到这一点的最好方法?
在Mac OS中,您可以使用“打开”命令。 有一个Windows API调用做类似的事情,但我不记得它。
更新
好吧,“开始”命令将执行它,所以这应该工作。
Mac OS / X:
os.system("open "+filename)
视窗:
os.system("start "+filename)
很多后来由Edward更新:os.system工作,但它只适用于文件名中没有任何空格的文件夹和文件(例如A:\ abc \ def \ a.txt) 。
稍后更新
好吧,显然这个愚蠢的屁股争论仍在继续,所以让我们看看这个子过程。
open
和start
分别为Mac OS / X和Windows命令解释器的东西。 现在,假设我们使用subprocess。 通常,你会使用:
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
那么这有什么好处呢? 从理论上讲,这是更安全的 – 但事实上,我们需要以某种方式执行命令行。 无论在哪种环境下,我们都需要环境和服务来介入,获得path等等。 在任何情况下,我们都不执行任意文本,所以它没有一个固有的“但是你可以键入'filename ; rm -rf /'
”的问题,如果文件名可以被破坏,使用subprocess.call
给我们保护。
它实际上并没有给我们更多的错误检测,在这两种情况下我们都依赖于retcode
。 我们不需要等待subprocess,因为我们是通过问题陈述开始一个单独的进程。
“但是, subprocess
是首选。” 然而, os.system()
不被弃用,而且它是这个特定工作最简单的工具。
结论:使用os.system()
是最简单,最直接的方法,因此是一个正确的答案。
使用Python os.system()
上的subprocess
os.system()
模块,而不是os.system()
,所以你不必处理shell转义。
import subprocess, os if sys.platform.startswith('darwin'): subprocess.call(('open', filepath)) elif os.name == 'nt': os.startfile(filepath) elif os.name == 'posix': subprocess.call(('xdg-open', filepath))
双圆括号是因为subprocess.call()
一个序列作为它的第一个参数,所以我们在这里使用一个元组。 在使用Gnome的Linux系统上,还有一个gnome-open
命令可以完成同样的任务,但是xdg-open
是Free Desktop Foundation的标准,可以在Linux桌面环境中工作。
为了完整性(这不是问题), xdg-open将在Linux上执行相同的操作。
我更喜欢:
os.startfile(path, 'open')
请注意,此模块支持文件夹和文件中具有空格的文件名,例如
A:\abc\folder with spaces\file with-spaces.txt
( python文档 )“打开”不需要添加(这是默认的)。 文档特别提到这就像在Windows资源pipe理器中双击文件的图标。
此解决scheme仅适用于Windows。
import os import subprocess def click_on_file(filename): try: os.startfile(filename): except AttributeError: subprocess.call(['open', filename])
如果你必须使用启发式的方法,你可以考虑webbrowser
。
这是标准库,尽pipe它的名字,它也会尝试打开文件:
请注意,在某些平台上,尝试使用此function打开文件名可能会起作用并启动操作系统的关联程序。 但是,这既不支持也不便携。 ( 参考 )
我试过这个代码,它在Windows 7和Ubuntu Natty中工作正常:
import webbrowser webbrowser.open("path_to_file")
此代码在Windows XP Professional中使用Internet Explorer 8也可以正常工作。
开始不支持长path名称和空格。 您必须将其转换为8.3兼容的path。
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调用。
如果你想要使用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
方法正确引用了参数,但是start
命令的语法却很奇怪,其中:
start notes.txt
除了:
start "notes.txt"
第一个引用的string应该设置窗口的标题。 为了使它与空间一起工作,我们必须这样做:
start "" "my notes.txt"
这是上面的代码。
我很晚了,但这里是使用Windows API的解决scheme。 这总是打开关联的应用程序。
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(path,'open')在windows下是好的,因为当目录中有空格时,os.system('start',path_name)无法打开应用程序,当i18n存在于目录os时。系统需要在Windows中将unicode更改为控制台的编解码器。
在Mac OS上,您可以调用“打开”
import os os.popen("open myfile.txt")
这将打开与文本编辑文件,或任何应用程序设置为此文件types的默认值
如果您想指定应用程序以在Mac OS X上打开该文件,请使用以下命令: os.system("open -a [app name] [file name]")
在Windows 8.1,下面已经工作,而其他给定的方式与subprocess.call
失败,path中有空格。
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))