问题描述
我需要能够在 Windows 和 Mac OS 中使用其默认应用程序打开文档.基本上,我想做与在资源管理器或 Finder 中双击文档图标时发生的相同的事情.在 Python 中执行此操作的最佳方法是什么?
open
和 start
分别是 Mac OS/X 和 Windows 的命令解释器这个.
要从 Python 调用它们,您可以使用 subprocess
模块或 os.system()
.
以下是关于使用哪个包的注意事项:
您可以通过
os.system
调用它们,虽然可行,但是...转义:
os.system
仅适用于路径名中没有任何空格或其他 shell 元字符的文件名(例如A:abcdefa.txt
),否则这些都需要转义.对于类 Unix 系统有shlex.quote
,但对于 Windows 没有真正的标准.也许还可以参见 python、windows:使用 shlex 解析命令行>- MacOS/X:
os.system("open " + shlex.quote(filename))
- Windows:
os.system("start " + filename)
正确地说,filename
也应该被转义.
- MacOS/X:
您也可以通过
subprocess
模块调用它们,但是...对于 Python 2.7 及更新版本,只需使用
subprocess.check_call(['open', filename])
在 Python 3.5+ 中,您可以等效地使用稍微复杂但也更通用的
subprocess.run(['open', filename], check=True)
如果你需要一直兼容到 Python 2.4,你可以使用
subprocess.call()
并实现你自己的错误检查:尝试:retcode = subprocess.call("打开" + 文件名,shell=True)如果重新编码
现在,使用
subprocess
有什么好处?- 安全性:理论上,这更安全,但实际上我们需要以一种或另一种方式执行命令行;在任一环境中,我们都需要环境和服务来解释、获取路径等.在这两种情况下,我们都不会执行任意文本,因此它没有固有的但您可以键入
'filename ; rm -rf/'
"问题,以及 if文件名可能会被破坏,使用subprocess.call
几乎没有额外的保护. - 错误处理:它实际上并没有给我们更多的错误检测,在任何一种情况下我们仍然依赖于
retcode
;但是在发生错误时显式引发异常的行为肯定会帮助您注意到是否存在故障(尽管在某些情况下,回溯可能根本没有比简单地忽略错误更有帮助). - 产生一个(非阻塞)子进程:我们不需要等待子进程,因为我们是根据问题陈述启动一个单独的进程.
反对但首选
subprocess
".然而,os.system()
并没有被弃用,它在某种意义上是这个特定工作的最简单的工具.结论:因此使用os.system()
也是一个正确的答案.一个明显的缺点是 Windows
start
命令要求你传入shell=True
否定使用subprocess
的大部分好处.- 安全性:理论上,这更安全,但实际上我们需要以一种或另一种方式执行命令行;在任一环境中,我们都需要环境和服务来解释、获取路径等.在这两种情况下,我们都不会执行任意文本,因此它没有固有的但您可以键入
I need to be able to open a document using its default application in Windows and Mac OS. Basically, I want to do the same thing that happens when you double-click on the document icon in Explorer or Finder. What is the best way to do this in Python?
open
and start
are command-interpreter things for Mac OS/X and Windows respectively, to do this.
To call them from Python, you can either use subprocess
module or os.system()
.
Here are considerations on which package to use:
You can call them via
os.system
, which works, but...Escaping:
os.system
only works with filenames that don't have any spaces or other shell metacharacters in the pathname (e.g.A:abcdefa.txt
), or else these need to be escaped. There isshlex.quote
for Unix-like systems, but nothing really standard for Windows. Maybe see also python, windows : parsing command lines with shlex- MacOS/X:
os.system("open " + shlex.quote(filename))
- Windows:
os.system("start " + filename)
where properly speakingfilename
should be escaped, too.
- MacOS/X:
You can also call them via
subprocess
module, but...For Python 2.7 and newer, simply use
subprocess.check_call(['open', filename])
In Python 3.5+ you can equivalently use the slightly more complex but also somewhat more versatile
subprocess.run(['open', filename], check=True)
If you need to be compatible all the way back to Python 2.4, you can use
subprocess.call()
and implement your own error checking: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
Now, what are the advantages of using
subprocess
?- Security: In theory, this is more secure, but in fact we're needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth. In neither case are we executing arbitrary text, so it doesn't have an inherent "but you can type
'filename ; rm -rf /'
" problem, and if the file name can be corrupted, usingsubprocess.call
gives us little additional protection. - Error handling: It doesn't actually give us any more error detection, we're still depending on the
retcode
in either case; but the behavior to explicitly raise an exception in the case of an error will certainly help you notice if there is a failure (though in some scenarios, a traceback might not at all be more helpful than simply ignoring the error). - Spawns a (non-blocking) subprocess: We don't need to wait for the child process, since we're by problem statement starting a separate process.
To the objection "But
subprocess
is preferred." However,os.system()
is not deprecated, and it's in some sense the simplest tool for this particular job. Conclusion: usingos.system()
is therefore also a correct answer.A marked disadvantage is that the Windows
start
command requires you to pass inshell=True
which negates most of the benefits of usingsubprocess
.- Security: In theory, this is more secure, but in fact we're needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth. In neither case are we executing arbitrary text, so it doesn't have an inherent "but you can type
这篇关于在 Windows 和 Mac OS 中使用 Python 中的默认操作系统应用程序打开文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!