web-dev-qa-db-ja.com

WindowsおよびMac OSの両方で、PythonのデフォルトOSアプリケーションでドキュメントを開きます

WindowsおよびMac OSでデフォルトのアプリケーションを使用してドキュメントを開くことができる必要があります。基本的に、ExplorerまたはFinderでドキュメントアイコンをダブルクリックしたときと同じことを行います。 Pythonでこれを行う最良の方法は何ですか?

108
Abdullah Jibaly

openstartは、Mac OS/XとWindows用のコマンドインタープリターです。

Pythonから呼び出すには、subprocessモジュールまたはos.system()を使用できます。

使用するパッケージに関する考慮事項は次のとおりです。

  1. それらはos.system経由で呼び出すことができますが、機能しますが...

    Escaping:os.systemは、パス名にスペースや他のシェルメタキャラクターが含まれていないファイル名(例:A:\abc\def\a.txt)でのみ動作します。そうでない場合はエスケープする必要があります。 Unixライクなシステムにはshlex.quoteがありますが、Windowsには本当に標準的なものはありません。多分 python、windows:コマンドラインを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 /'を入力できます」という問題はありません。また、 if を使用すると、subprocess.call少しの追加保護。
    • エラー処理:実際にこれ以上エラーを検出することはありません。どちらの場合でもretcodeに依存しています。ただし、エラーの場合に明示的に例外を発生させる動作は、障害がある場合に確実に気付くのに役立ちます(ただし、一部のシナリオでは、トレースバックはエラーを単に無視するよりも役に立たない場合があります)。
    • (非ブロッキング)サブプロセスを生成します:子プロセスを待つ必要はありません。問題ステートメントによって別のプロセスを開始しているためです。

    反対意見に対して「しかし、subprocessが望ましい」。ただし、os.system()は非推奨ではなく、ある意味ではこの特定のジョブの最も単純なツールです。結論:したがって、os.system()を使用することも正しい答えです。

    マークされた短所は、Windowsのstartコマンドrequiresを使用してShell=Trueを渡すことで、subprocessを使用する利点のほとんどが無効になる。

59
Charlie Martin

Python 2.4 +、os.system()ではなく)で利用可能なsubprocessモジュールを使用してください。そのため、シェルのエスケープに対処する必要はありません。

_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()が最初の引数としてシーケンスを必要としているため、ここでTupleを使用しています。 Gnomeを搭載したLinuxシステムには、同じことを行う_gnome-open_コマンドもありますが、_xdg-open_はFree Desktop Foundationの標準であり、Linuxデスクトップ環境全体で機能します。

132
Nick

私が好む:

os.startfile(path, 'open')

このモジュールは、フォルダーやファイルにスペースを含むファイル名をサポートしていることに注意してください。

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

python docs ) 'open'を追加する必要はありません(デフォルトです)。ドキュメントでは、これはWindowsエクスプローラーでファイルのアイコンをダブルクリックするようなものであると明確に述べられています。

このソリューションはWindowsのみです。

36
DrBloodmoney

完全を期すため(質問にはありませんでした)、Linuxでは xdg-open が同じことを行います。

32
dF.
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])
22
nosklo

ヒューリスティックな方法を使用する必要がある場合は、webbrowserを検討できます。
これは標準ライブラリであり、その名前にもかかわらず、ファイルを開こうとします。

一部のプラットフォームでは、この関数を使用してファイル名を開こうとすると、動作し、オペレーティングシステムの関連プログラムが起動する場合があります。ただし、これはサポートされておらず、移植性もありません。 ( 参照

このコードを試してみましたが、Windows 7とUbuntu Nattyで問題なく動作しました。

import webbrowser
webbrowser.open("path_to_file")

このコードは、Internet Explorer 8を使用するWindows XP Professionalでも正常に機能します。

19
etuardu

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呼び出しを使用するには、ファイルが存在している必要があります。

4
bFloch

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"

これが上のコードがすることです。

4
Tomas Sedovic

かなり遅れていますが、ここではwindows apiを使用したソリューションを示します。これにより、常に関連付けられたアプリケーションが開きます。

import ctypes

Shell32 = ctypes.windll.Shell32
file = 'somedocument.doc'

Shell32.ShellExecuteA(0,"open",file,0,0,5)

多くの魔法の定数。最初のゼロは、現在のプログラムのhwndです。ゼロにすることができます。他の2つのゼロはオプションのパラメーター(パラメーターとディレクトリ)です。 5 == SW_SHOW、アプリの実行方法を指定します。詳細については、 ShellExecute API docs を参照してください。

2
George

os.startfile(path、 'open')は、ディレクトリの下にスペースが存在する場合、os.system( 'start'、path_name)がアプリを正しく開けず、i18nがディレクトリosに存在する場合に適しています。システムは、ユニコードをWindowsのコンソールのコーデックに変更する必要があります。

1
BearPy

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))
0
Ch.Idea

Mac OS Xでファイルを開くアプリを指定する場合は、os.system("open -a [app name] [file name]")を使用します

0
eppsilon

mac OSでは、「open」を呼び出すことができます

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

これは、TextEdit、またはこのファイルタイプのデフォルトとして設定されているアプリでファイルを開きます

0
lcvinny