Windows 및 Mac OS 모두에서 Python의 기본 OS 응용 프로그램으로 문서 열기


126

Windows 및 Mac OS에서 기본 응용 프로그램을 사용하여 문서를 열 수 있어야합니다. 기본적으로 Explorer 또는 Finder에서 문서 아이콘을 두 번 클릭 할 때 발생하는 것과 동일한 작업을 수행하고 싶습니다. 파이썬에서 이것을 수행하는 가장 좋은 방법은 무엇입니까?


9
2008 년부터 Python 추적기의 표준 라이브러리에 포함되는 문제가있었습니다. bugs.python.org/issue3177
Ram Rachum 2011

답변:


77

open그리고 start이 일을 맥 OS / X 및 Windows 명령 인터프리터 가지 각각이다.

Python에서 호출하려면 subprocessmodule 또는 os.system().

사용할 패키지에 대한 고려 사항은 다음과 같습니다.

  1. 을 통해 전화를 걸 수 os.system있지만 작동하지만 ...

    이스케이프 : os.system 경로 이름에 공백이나 다른 쉘 메타 문자가없는 파일 이름 (예 :) 에서만 작동합니다. 그렇지 않으면 A:\abc\def\a.txt이스케이프해야합니다. 이 shlex.quote유닉스 시스템,하지만 윈도우 아무것도 정말 표준입니다. python, windows : shlex로 명령 줄 구문 분석을 참조하십시오 .

    • 맥 OS 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 /'"문제를, 그리고 경우 파일 이름이 손상 될 수 있으며, 사용하는 것은 subprocess.call우리에게 약간의 추가적인 보호 기능을 제공합니다.
    • 오류 처리 : 실제로 더 이상 오류 감지를 제공하지 않습니다 retcode. 두 경우 모두 여전히 의존 하고 있습니다. 그러나 오류가 발생한 경우 명시 적으로 예외를 발생시키는 동작은 오류가 있는지 확인하는 데 확실히 도움이됩니다 (일부 시나리오에서는 추적이 단순히 오류를 무시하는 것보다 더 도움이되지 않을 수 있음).
    • (비 차단) 하위 프로세스 생성 : 별도의 프로세스를 시작하는 문제 설명으로 인해 하위 프로세스를 기다릴 필요가 없습니다.

    이의 제기 "하지만 subprocess선호됩니다." 그러나 os.system()는 더 이상 사용되지 않으며 어떤 의미에서는이 특정 작업을위한 가장 간단한 도구입니다. 결론 : os.system()따라서 사용도 정답입니다.

    표시 단점은 윈도우이다 start명령은 필요 에 전달할 수 shell=True있는 사용의 이점의 대부분을 부정 subprocess.


2
filename형식이 어디인지에 따라 이것은 os.system ()이 안전하지 않고 나쁜 이유에 대한 완벽한 예입니다. 하위 프로세스가 더 좋습니다.
Devin Jeanpierre

6
Nick의 대답은 괜찮아 보였습니다. 방해가되지 않았습니다. 잘못된 예를 사용하여 설명하는 것은 쉽게 정당화 할 수 없습니다.
Devin Jeanpierre

2
하위 프로세스를 사용하는 것보다 덜 안전하고 유연성이 떨어집니다. 그것은 나에게 잘못된 것 같습니다.
Devin Jeanpierre

8
물론 중요합니다. 좋은 대답과 나쁜 대답 (또는 끔찍한 대답)의 차이입니다. os.system () 문서 자체에 "서브 프로세스 모듈 사용"이라고되어 ​​있습니다. 무엇이 더 필요합니까? 그것은 저에게 충분히 비추천입니다.
Devin Jeanpierre

20
이 토론을 다시 시작하는 것을 조금 꺼려하지만 "나중 업데이트"섹션이 완전히 잘못되었다고 생각합니다. 문제 os.system()는 쉘을 사용한다는 것입니다 (그리고 여기서 쉘 이스케이프를 수행하지 않으므로 쉘 메타 문자를 포함하는 완벽하게 유효한 파일 이름에 대해 나쁜 일이 발생합니다). subprocess.call()선호 되는 이유는를 사용하여 셸을 우회 할 수있는 옵션 이 있기 때문 subprocess.call(["open", filename])입니다. 이것은 모든 유효한 파일 이름에 대해 작동하며 신뢰할 수없는 파일 이름에 대해서도 쉘 주입 취약점을 유발하지 않습니다.
Sven Marnach

151

subprocessPython 2.4 이상에서 사용 가능한 모듈을 사용하십시오. os.system()따라서 쉘 이스케이프를 처리 할 필요가 없습니다.

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-openFree Desktop Foundation 표준이며 Linux 데스크톱 환경에서 작동 하는 명령 도 있습니다.


5
subprocess.call ()에서 'start'를 사용하는 것은 Windows에서 작동하지 않습니다. start는 실제로 실행 파일이 아닙니다.
Tomas Sedovic

4
nitpick : 모든 linuxen (그리고 대부분의 BSD)에서 사용해야합니다. xdg-open- linux.die.net
man

6
Windows에서 시작은 실행 파일이 아닌 쉘 명령입니다. subprocess.call (( 'start', filepath), shell = True)를 사용할 수 있지만 셸에서 실행하는 경우 os.system을 사용할 수도 있습니다.
Peter Graham

나는 실행 xdg-open test.py했고 그것은 나를 위해 firefox 다운로드 대화 상자를 열었습니다. 뭐가 문제 야? 나는 manjaro linux에 있습니다.
제이슨

1
@Jason xdg-open구성이 혼란스러운 것처럼 들리지만 실제로는 의견에서 문제를 해결할 수있는 문제가 아닙니다. 아마도 unix.stackexchange.com/questions/36380/…을
tripleee

44

나는 선호한다:

os.startfile(path, 'open')

이 모듈은 폴더와 파일에 공백이있는 파일 이름을 지원합니다.

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

( python docs ) 'open'은 추가 할 필요가 없습니다 (기본값). 문서에서는 Windows 탐색기에서 파일 아이콘을 두 번 클릭하는 것과 같음을 구체적으로 언급합니다.

이 솔루션은 Windows 전용입니다.


감사. 문서가 마지막 단락에 추가 되었기 때문에 가용성을 알지 못했습니다. 대부분의 다른 섹션에서 가용성 메모는 자체 라인을 차지합니다.
DrBloodmoney

Linux에서는 어떤 이유로 든 오류가 발생 startfile하지 않고 함수가 존재하지 않습니다. 즉, 사용자는 누락 된 함수에 대해 혼란스러운 오류 메시지를 받게됩니다. 이를 피하기 위해 플랫폼을 확인하는 것이 좋습니다.
cz

39

완전성을 위해 (문제가 아님) xdg-open 은 Linux에서 동일한 작업을 수행합니다.


6
+1 일반적으로 응답자는 요청되지 않은 질문에 답변해서는 안되지만이 경우 SO 커뮤니티 전체에 매우 관련성이 높고 도움이된다고 생각합니다.
demongolem

이것을 찾고 있었다
nurettin

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

2
허, 나는 startfile에 대해 몰랐습니다. Mac과 Linux 버전의 Python이 유사한 의미를 선택한다면 좋을 것입니다.
Nick

3
관련 파이썬 버그 : bugs.python.org/issue3177- 멋진 패치를 제공하면 받아 들여질 수 있습니다. =)
gnud

Linux 용
xdg

21

휴리스틱 방법을 사용해야하는 경우를 고려할 수 있습니다 webbrowser.
표준 라이브러리이며 이름에도 불구하고 파일을 열려고 시도합니다.

일부 플랫폼에서는이 기능을 사용하여 파일 이름을 열려고하면 작동하고 운영 체제 관련 프로그램이 시작될 수 있습니다. 그러나 이것은 지원되거나 이식 가능하지 않습니다. ( 참조 )

이 코드를 시도했지만 Windows 7 및 Ubuntu Natty에서 제대로 작동했습니다.

import webbrowser
webbrowser.open("path_to_file")

이 코드는 Internet Explorer 8을 사용하는 Windows XP Professional에서도 잘 작동합니다.


3
내가 말할 수있는 한, 이것이 가장 좋은 대답입니다. 크로스 플랫폼으로 보이며 어떤 플랫폼이 사용 중인지 확인하거나 OS, 플랫폼을 가져올 필요가 없습니다.
polandeer

2
@jonathanrocher : 소스 코드에 Mac 지원이 있습니다 . 그것은 사용하는 open location유효한 URL로 경로를 제공하는 경우가 해결해야이.
jfs

1
macOS :import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
Daniel Springer

3
docs.python.org/3/library/webbrowser.html#webbrowser.open "일부 플랫폼에서 [webbrowser.open (url)]을 사용하여 파일 이름을 열려고하면 작동하고 운영 체제 관련 프로그램을 시작할 수 있습니다. 그러나 ,이 기능은 지원되거나 이식 가능하지 않습니다. "
nyanpasu64

6

계속 진행하려면 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에 공백이없는 경우에만 가능합니다.

while subprocess.call방법en 는 매개 변수를 적절하게 인용start 명령에는 다소 이상한 구문이 있습니다.

start notes.txt

다음 이외의 작업을 수행합니다.

start "notes.txt"

첫 번째 인용 문자열은 창의 제목을 설정해야합니다. 공간에서 작동하도록하려면 다음을 수행해야합니다.

start "" "my notes.txt"

그게 위에있는 코드가하는 일입니다.


5

시작은 긴 경로 이름과 공백을 지원하지 않습니다. 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 호출을 사용하려면 파일이 있어야합니다.


1
또 다른 해결 방법은 제목을 따옴표로 start "Title" "C:\long path to\file.avi"
묶는 것입니다.

3

나는 꽤 늦었지만 여기에 Windows API를 사용하는 솔루션이 있습니다. 이렇게하면 항상 연결된 응용 프로그램이 열립니다.

import ctypes

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

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

많은 마법 상수. 첫 번째 0은 현재 프로그램의 hwnd입니다. 0 일 수 있습니다. 다른 두 개의 0은 선택적 매개 변수 (매개 변수 및 디렉토리)입니다. 5 == SW_SHOW, 앱 실행 방법을 지정합니다. 자세한 정보 는 ShellExecute API 문서 를 읽어보십시오 .


1
그것은 어떻게 비교 os.startfile(file)됩니까?
jfs 2011

2

Mac OS에서는 'open'이라고 부를 수 있습니다.

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

그러면 TextEdit로 파일이 열리거나이 파일 형식에 대해 기본값으로 설정된 모든 앱이 열립니다.


2

Mac OS X에서 파일을 열 앱을 지정하려면 다음을 사용하십시오. os.system("open -a [app name] [file name]")


2

Windows 8.1에서 아래는 subprocess.call경로에 공백이 있는 다른 주어진 방법으로 작동했습니다.

subprocess.call('cmd /c start "" "any file path with spaces"')

이전에 this 및 other의 답변을 활용하여 여러 플랫폼에서 작동하는 인라인 코드가 있습니다.

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

2

os.startfile(path, 'open')디렉터리에 공백이 os.system('start', path_name)있으면 앱을 제대로 열 수없고 디렉터리에 i18n이 있으면 os.system유니 코드를 Windows 콘솔의 코덱으로 변경해야하기 때문에 Windows에서는 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.