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.