在 Windows 和 Mac OS 中使用 Python 中的默认操作系统应用程序打开文档

2024-12-19 09:24:00
admin
原创
111
摘要:问题描述:我需要能够使用 Windows 和 Mac OS 中的默认应用程序打开文档。基本上,我想执行与双击 Explorer 或 Finder 中的文档图标时相同的操作。在 Python 中执行此操作的最佳方法是什么?解决方案 1:使用subprocessPython 2.4+ 上可用的模块,而不是os.s...

问题描述:

我需要能够使用 Windows 和 Mac OS 中的默认应用程序打开文档。基本上,我想执行与双击 Explorer 或 Finder 中的文档图标时相同的操作。在 Python 中执行此操作的最佳方法是什么?


解决方案 1:

使用subprocessPython 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-open命令可以执行相同的操作,但xdg-open它是自由桌面基金会标准,并且可以在 Linux 桌面环境中使用。

解决方案 2:

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

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

关于使用哪个包,请考虑以下事项:

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

转义: os.system仅适用于路径名中没有任何空格或其他 shell 元字符的文件名(例如A:abcdefa.txt),否则需要对其进行转义。Unixshlex.quote类系统有转义,但 Windows 并没有真正的标准。也许还可以参见python、windows:使用 shlex 解析命令行

* MacOS / X:`os.system("open " + shlex.quote(filename))`
* Windows:`os.system("start " + filename)`严格来说`filename`也应该进行转义。
  1. 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 /'`”问题,并且**如果**文件名可能被破坏,则使用`subprocess.call`不会给我们带来额外的保护。
* **错误处理:**它实际上并没有为我们提供任何错误检测,`retcode`在任何一种情况下我们仍然依赖于;但是在发生错误时明确引发异常的行为肯定会帮助您注意到是否存在故障(尽管在某些情况下,回溯可能并不比简单地忽略错误更有帮助)。
* **生成一个(非阻塞)子进程**:我们不需要等待子进程,因为我们通过问题陈述启动一个单独的进程。对于反对意见“但`subprocess`更可取”。然而,`os.system()`并没有被弃用,从某种意义上说,它是这项特定工作最简单的工具。结论:`os.system()`因此使用也是一个正确的答案。

一个明显的缺点是 Windowsstart命令要求您传入,shell=True这抵消了使用的大部分好处subprocess

解决方案 3:

我更喜欢:

os.startfile(path, 'open')

请注意,此模块支持文件夹和文件中带有空格的文件名,例如

A:abcolder with spacesile with-spaces.txt

( python 文档) 无需添加“open”(这是默认设置)。文档特别提到,这就像在 Windows 资源管理器中双击文件图标一样。

此解决方案仅适用于 Windows。

解决方案 4:

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

解决方案 5:

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

解决方案 6:

如果你必须使用启发式方法,你可以考虑webbrowser

它是标准库,尽管它的名字如此,它也会尝试打开文件:

请注意,在某些平台上,尝试使用此函数打开文件名可能会起作用并启动操作系统的关联程序。但是,这既不受支持也不可移植。(参考)

我尝试了此代码并且它在 Windows 7 和 Ubuntu Natty 中运行良好:

import webbrowser
webbrowser.open("path_to_file")

此代码在 Windows XP Professional 中使用 Internet Explorer 8 也能正常运行。

解决方案 7:

如果你想按照这种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方法en正确地引用了参数,但是该start命令的语法相当奇怪,其中:

start notes.txt

除以下之外还做了其他事情:

start "notes.txt"

第一个带引号的字符串应该设置窗口的标题。为了使其与空格兼容,我们必须这样做:

start "" "my notes.txt"

这就是上面的代码所做的事情。

解决方案 8:

Start 不支持长路径名和空格。您必须将其转换为兼容 8.3 的路径。

import subprocess
import win32api

filename = "C:\\Documents and Settings\/user\\Desktopile.avi"
filename_short = win32api.GetShortPathName(filename)

subprocess.Popen('start ' + filename_short, shell=True )

该文件必须存在才能与 API 调用一起工作。

解决方案 9:

os.startfile(path, 'open')在 Windows 下是好的,因为当目录中存在空格时,os.system('start', path_name)无法正确打开应用程序,并且当目录中存在 i18n 时,os.system需要将 unicode 更改为 Windows 中控制台的编解码器。

解决方案 10:

以下是 Nick 的回答,针对 WSL 稍作了调整:

import os
import sys
import logging
import subprocess

def get_platform():
    if sys.platform == 'linux':
        try:
            proc_version = open('/proc/version').read()
            if 'Microsoft' in proc_version:
                return 'wsl'
        except:
            pass
    return sys.platform

def open_with_default_app(filename):
    platform = get_platform()
    if platform == 'darwin':
        subprocess.call(('open', filename))
    elif platform in ['win64', 'win32']:
        os.startfile(filename.replace('/','\\'))
    elif platform == 'wsl':
        subprocess.call('cmd.exe /C start'.split() + [filename])
    else:                                   # linux variants
        subprocess.call(('xdg-open', filename))

解决方案 11:

我来晚了,但这里有一个使用 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 文档了解更多信息。

解决方案 12:

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

解决方案 13:

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

解决方案 14:

在 mac os 上你可以调用open

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

这将使用 TextEdit 或为此文件类型设置为默认的任何应用程序打开该文件。

解决方案 15:

我建立了一个小型库,结合了这里最好的答案来实现跨平台支持:

$ pip install universal-startfile

然后启动一个文件或者 URL:

from startfile import startfile

startfile("~/Downloads/example.png")
startfile("http://example.com")

解决方案 16:

我想您可能想在编辑器中打开文件。

对于 Windows

subprocess.Popen(["notepad", filename])

对于 Linux

subprocess.Popen(["text-editor", filename])

解决方案 17:

调用 open file() 函数时出现错误。我按照指南操作,但指南是在 Windows 中编写的,而我在 Linux 上。因此 os.statrfile 方法对我不起作用。我可以通过执行以下操作来缓解此问题:

导入库

import sys, os, subprocess
import tkinter
import tkinter.filedioalog as fd
import tkinter.messagebox as mb

导入库之后,我调用子进程方法在基于 unix 的操作系统中打开文件,即“xdg-open”和将要打开的文件。

def open_file():
     file = fd.askopenfilename(title='Choose a file of any type', filetypes=[('All files', "*.*")])
     subprocess.call(['xdg-open', file])

解决方案 18:

现在,这就像安装shopen并执行一样简单

import shopen
shopen.open(filepath)

欢迎反馈!


shutil.open值得一提的是,这可能最终会按照python/cpython#47427在标准库中实现,但那里的开发似乎在 2012 年停滞了。

与此同时,最好的选择仍然是os.startfile和特殊情况subprocess调用的组合,正如最高投票答案https://stackoverflow.com/a/435669所建议的那样。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用