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

稍后更新

好吧,显然这个愚蠢的屁股争论仍在继续,所以让我们看看这个子过程。

openstart分别为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))