使用Python中的默认OS应用程序打开文档,包括Windows和Mac OS

时间:2009-01-12 06:23:51

标签: python windows macos

我需要能够使用Windows和Mac OS中的默认应用程序打开文档。基本上,我想做同样的事情,当你双击资源管理器或Finder中的文档图标时发生的事情。在Python中执行此操作的最佳方法是什么?

13 个答案:

答案 0 :(得分:132)

使用Python 2.4+上提供的subprocess模块,而不是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桌面环境。

答案 1 :(得分:57)

openstart分别是Mac OS / X和Windows的命令解释器,用于执行此操作。

要从Python调用它们,您可以使用subprocess模块或os.system()

以下是使用哪个包的注意事项:

  1. 您可以通过os.system来调用它们,但是......

    转义: os.system仅适用于路径名中没有任何空格或其他shell元字符的文件名(例如A:\abc\def\a.txt),否则这些必须是逃过一劫。类似Unix的系统有shlex.quote,但没有什么真正适合Windows。也许还可以参见python, windows : parsing command lines with shlex

    • MacOS / X:os.system("open " + shlex.quote(filename))
    • Windows:os.system("start " + filename)正确说法filename也应该被转义。
  2. 您也可以通过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 /'”问题,而如果文件名可能会被破坏,使用{{1为我们提供了额外的保护。
    • 错误处理:它实际上没有给我们任何错误检测,在任何一种情况下我们仍然依赖于subprocess.call;但是在出现错误的情况下显式引发异常的行为肯定会帮助您注意到是否存在故障(尽管在某些情况下,回溯可能根本不会比简单地忽略错误更有帮助。)
    • 产生一个(非阻塞)子流程:我们不需要等待子流程,因为我们是通过问题陈述开始一个单独的流程。

    反对意见“但retcode是首选。”但是,subprocess并未弃用,从某种意义上说,它是这项特定工作的最简单工具。结论:因此使用os.system()也是正确的答案。

    标记为缺点的是,os.system()命令要求传入start,否定了使用shell=True带来的大部分好处1}}。

答案 2 :(得分:33)

我更喜欢:

os.startfile(path, 'open')

请注意,此模块支持在其文件夹和文件中包含空格的文件名,例如

A:\abc\folder with spaces\file with-spaces.txt

python docs)'open'不必添加(这是默认值)。文档特别提到这就像在Windows资源管理器中双击文件的图标一样。

此解决方案仅限Windows。

答案 3 :(得分:31)

仅仅为了完整性(问题不在其中),xdg-open将在Linux上执行相同操作。

答案 4 :(得分:21)

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

答案 5 :(得分:19)

如果必须使用启发式方法,可以考虑webbrowser 它的标准库,尽管它的名称,它也会尝试打开文件:

  

请注意,在某些平台上,尝试使用此方法打开文件名   功能,可以工作并启动操作系统的关联   程序。但是,既不支持也不便携。   (Reference

我试过这段代码,它在Windows 7和Ubuntu Natty中运行良好:

import webbrowser
webbrowser.open("path_to_file")

此代码在Windows XP Professional中也可以使用Internet Explorer 8正常工作。

答案 6 :(得分:4)

如果你想采用subprocess.call()方式,它应该在Windows上看起来像这样:

import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))

你不能只使用:

subprocess.call(('start', FILE_NAME))

因为start is not an executable而是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"

这就是顶部的代码。

答案 7 :(得分:4)

Start不支持长路径名和空格。您必须将其转换为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​​调用。

答案 8 :(得分:2)

我已经很晚了,但这是一个使用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 docs了解更多信息。

答案 9 :(得分:1)

windows下的os.startfile(path,&#39; open&#39;)很好,因为当目录中存在空格时,os.system(&#39; start&#39;,path_name)就不能了正确打开应用程序,当目录中存在i18n时,os.system需要将unicode更改为Windows中控制台的编解码器。

答案 10 :(得分:0)

在mac os上你可以调用'open'

import os
os.popen("open myfile.txt")

这将使用TextEdit打开文件,或者将此文件类型设置为默认应用程序

答案 11 :(得分:0)

如果要指定应用程序以在Mac OS X上打开文件,请使用以下命令: os.system("open -a [app name] [file name]")

答案 12 :(得分:0)

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