在Windows和Mac操作系统中,使用Python中的默认操作系统应用程序打开文档
我需要能够在Windows和Mac OS中使用默认应用程序打开文档。基本上,我想做的事情与在Explorer或Finder中双击文档图标时发生的事情相同。在Python中执行此操作的最佳方法是什么?在Windows和Mac操作系统中,使用Python中的默认操作系统应用程序打开文档,python,windows,macos,Python,Windows,Macos,我需要能够在Windows和Mac OS中使用默认应用程序打开文档。基本上,我想做的事情与在Explorer或Finder中双击文档图标时发生的事情相同。在Python中执行此操作的最佳方法是什么?open和start分别是用于Mac OS/X和Windows的命令解释器 要从Python中调用它们,您可以使用子流程模块或os.system() 以下是使用哪个软件包的注意事项: 您可以通过os.system调用它们,这很有效,但是 转义:os.system仅适用于路径名中没有空格或其他shell
open
和start
分别是用于Mac OS/X和Windows的命令解释器
要从Python中调用它们,您可以使用子流程
模块或os.system()
以下是使用哪个软件包的注意事项:
os.system
调用它们,这很有效,但是
转义:os.system
仅适用于路径名中没有空格或其他shell元字符的文件名(例如A:\abc\def\A.txt
),否则这些文件名需要转义。对于类Unix系统有shlex.quote
,但对于Windows没有真正的标准。也许你也会看到
- MacOS/X:
os.system(“打开”+shlex.quote(文件名))
- Windows:
这里正确地说os.system(“开始”+filename)
也应该转义filename
子流程
模块调用它们,但是
对于Python2.7及更新版本,只需使用
subprocess.check_call(['open', filename])
在Python3.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
试试看:
retcode=subprocess.call(“打开”+文件名,shell=True)
如果retcode<0:
打印>>sys.stderr,“子项被信号终止”,-retcode
其他:
打印>>sys.stderr,“返回的子对象”,重新编码
除O错误外,e:
打印>>sys.stderr,“执行失败:”,e
现在,使用子流程的优点是什么
- 安全性:理论上,这更安全,但实际上我们需要以这种或那种方式执行命令行;在这两种环境中,我们都需要环境和服务来解释、获取路径等等。在这两种情况下,我们都不会执行任意文本,因此它没有固有的“但是您可以键入
'filename;rm-rf/'
”问题,并且如果文件名可能损坏,则使用子进程。call
几乎不会给我们额外的保护
- 错误处理:它实际上没有给我们更多的错误检测,我们仍然依赖于
retcode
;但是在发生错误的情况下显式引发异常的行为肯定会帮助您注意到是否存在故障(尽管在某些情况下,回溯可能不会比简单地忽略错误更有帮助)
- 生成一个(非阻塞)子进程:我们不需要等待子进程,因为我们是通过问题陈述启动一个单独的进程
对于反对意见,“但是子流程
是首选的。”然而,os.system()
并没有被弃用,从某种意义上说,它是这个特定作业最简单的工具。结论:因此,使用os.system()
也是正确的答案
一个明显的缺点是Windowsstart
命令要求您传入shell=True
,这否定了使用子流程
的大部分好处
在mac os上,您可以调用
open
:
import os
os.open("open myfile.txt")
这将使用TextEdit打开文件,或者任何设置为此文件类型默认值的应用程序。我更喜欢:
os.startfile(path, 'open')
请注意,此模块支持文件夹和文件中有空格的文件名,例如
A:\abc\folder with spaces\file with-spaces.txt
()不必添加“打开”(这是默认设置)。文档特别提到,这就像在Windows资源管理器中双击文件图标一样
此解决方案仅适用于windows。仅为了完整性(这不是问题),将在Linux上执行相同的操作。使用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打开< /C>命令,它做同样的事情,但是<代码> XDG OPEN 是免费的桌面基础标准,它在Linux桌面环境下工作。 < P>如果您想指定应用程序在Mac OS X上打开文件,请使用:
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])
os.system(“打开-a[app name][file name]”
如果您想使用子流程.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))
但前提是文件名中没有空格
当subprocess.call
方法正确引用参数时,start
命令的语法相当奇怪,其中:
start notes.txt
做一些其他事情,而不是:
start "notes.txt"
第一个带引号的字符串应该设置窗口的标题。要使其与空间协同工作,我们必须做到:
start "" "my notes.txt"
这就是上面的代码所做的。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调用。我已经很晚了,但这里有一个使用windows API的解决方案。这将始终打开关联的应用程序
import ctypes
shell32 = ctypes.windll.shell32
file = 'somedocument.doc'
shell32.ShellExecuteA(0,"open",file,0,0,5)
很多神奇的常数。第一个零是当前程序的hwnd。可以是零。其他两个零是可选参数(参数和目录)。5==SW_SHOW,它指定如何执行应用程序。
阅读
了解更多信息。如果必须使用启发式方法
import webbrowser
webbrowser.open("path_to_file")
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))