विंडोज और मैक ओएस दोनों में पायथन में डिफॉल्ट ओएस एप्लीकेशन के साथ ओपन डॉक्यूमेंट


126

मुझे विंडोज और मैक ओएस में इसके डिफ़ॉल्ट एप्लिकेशन का उपयोग करके एक दस्तावेज़ खोलने में सक्षम होने की आवश्यकता है। मूल रूप से, मैं वही काम करना चाहता हूं जो तब होता है जब आप एक्सप्लोरर या खोजक में दस्तावेज़ आइकन पर डबल-क्लिक करते हैं। पायथन में ऐसा करने का सबसे अच्छा तरीका क्या है?


9
2008 से पायथन ट्रैकर में मानक पुस्तकालय में शामिल करने के लिए इसके लिए एक मुद्दा है: Bugs.python.org/issue3177
राम रचूम

जवाबों:


77

openऔर startऐसा करने के लिए क्रमशः मैक ओएस / एक्स और विंडोज के लिए कमांड-इंटरप्रेटर चीजें हैं।

उन्हें पायथन से बुलाने के लिए, आप या तो subprocessमॉड्यूल का उपयोग कर सकते हैं या os.system()

यहाँ पर विचार किया जाता है कि किस पैकेज का उपयोग करना है:

  1. आप उन्हें कॉल कर सकते हैं os.system, जो काम करता है, लेकिन ...

    बचना: os.system केवल उन फ़ाइलनामों के साथ काम करता है जिनके पास मार्गनाम (उदाहरण A:\abc\def\a.txt) में कोई रिक्त स्थान या अन्य शेल मेटाचैकर्स नहीं हैं , या फिर इन से बचने की आवश्यकता है। नहीं है shlex.quoteयूनिक्स सिस्टम के लिए, लेकिन वास्तव में विंडोज के लिए मानक कुछ भी नहीं। शायद अजगर, खिड़कियां भी देखें : श्लेक्स के साथ पार्सिंग कमांड लाइन

    • मैक ओएस एक्स: os.system("open " + shlex.quote(filename))
    • विंडोज: os.system("start " + filename)जहां ठीक से बोलने से filenameबचना चाहिए, भी।
  2. आप उन्हें subprocessमॉड्यूल के माध्यम से भी कॉल कर सकते हैं , लेकिन ...

    पायथन 2.7 और नए के लिए, बस का उपयोग करें

    subprocess.check_call(['open', filename])

    पायथन 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फॉर्म आता है, उसके आधार पर यह एक सटीक उदाहरण है कि क्यों ओ.एस.एस. () असुरक्षित और बुरा है। उपप्रकार बेहतर है।
डेविन जीनपिएरे

6
निक का जवाब मुझे ठीक लगा। रास्ते में कुछ नहीं मिला। गलत उदाहरणों का उपयोग करके चीजों की व्याख्या करना आसानी से उचित नहीं है।
डेविन जीनपिएरे

2
यह सबप्रोसेस का उपयोग करने से कम सुरक्षित और कम लचीला है। जो मुझे गलत लगता है।
डेविन जीनपिएरे

8
बेशक यह मायने रखता है। यह एक अच्छे उत्तर और एक बुरे उत्तर (या एक भयानक उत्तर) के बीच का अंतर है। Os.system () के लिए डॉक्स स्वयं कहते हैं "सबप्रोसेस मॉड्यूल का उपयोग करें।" और क्या चाहिए? यह मेरे लिए पर्याप्त है।
डेविन जीनपिएरे

20
मुझे इस चर्चा को फिर से शुरू करने में थोड़ी परेशानी महसूस हो रही है, लेकिन मुझे लगता है कि "बाद में अपडेट" सेक्शन पूरी तरह से गलत है। इसके साथ समस्या os.system()यह है कि यह शेल का उपयोग करता है (और आप यहां से बचने के लिए कोई शेल नहीं कर रहे हैं, इसलिए बैड थिंग्स पूरी तरह से वैध फाइलनाम के लिए होगा जो शेल मेटा-कैरेक्टर को समाहित करता है)। subprocess.call()पसंद किए जाने का कारण यह है कि आपके पास शेल का उपयोग करके बायपास करने का विकल्प है subprocess.call(["open", filename])। यह सभी मान्य फ़ाइलनामों के लिए काम करता है, और बिना फ़ाइल किए गए फ़ाइलनामों के लिए भी एक शेल-इंजेक्शन भेद्यता का परिचय नहीं देता है।
स्वेन मार्नाच

151

subprocessपायथन 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 के साथ लिनक्स सिस्टम पर एक gnome-openकमांड भी होता है जो समान कार्य करता है, लेकिन xdg-openफ्री डेस्कटॉप फाउंडेशन मानक है और लिनक्स डेस्कटॉप वातावरण में काम करता है।


5
सबप्रोसेस.कॉल () में 'स्टार्ट' का उपयोग करना विंडोज पर काम नहीं करता है - स्टार्ट वास्तव में एक निष्पादन योग्य नहीं है।
टॉमस सेडोविक

4
nitpick: सभी linuxen पर (और मुझे लगता है कि अधिकांश BSDs) का आपको उपयोग करना चाहिए xdg-open- linux.die.net/man/1/xdg-open
gnud

6
विंडोज पर शुरू करना एक शेल कमांड है, एक निष्पादन योग्य नहीं है। आप subprocess.call (('start', filepath), shell = True) का उपयोग कर सकते हैं, हालाँकि यदि आप किसी शेल में निष्पादित कर रहे हैं तो आप os.system का भी उपयोग कर सकते हैं।
पीटर ग्राहम

मैं भागा xdg-open test.pyऔर उसने मेरे लिए फ़ायरफ़ॉक्स डाउनलोड डायलॉग खोला। क्या गलत है? मैं मंजरो लाइन पर हूं।
जेसन

1
@ जैसन लगता है कि आपका xdg-openकॉन्फ़िगरेशन गड़बड़ है, लेकिन यह वास्तव में ऐसी चीज नहीं है जिसे हम एक टिप्पणी में समस्या निवारण कर सकते हैं। शायद unix.stackexchange.com/questions/36380/…
tripleee

44

मैं पसंद करता हूं:

os.startfile(path, 'open')

ध्यान दें कि यह मॉड्यूल उन फ़ाइलनामों का समर्थन करता है जिनके फ़ोल्डर और फ़ाइलों में रिक्त स्थान हैं उदा

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

( अजगर डॉक्स ) 'ओपन' को जोड़ना नहीं है (यह डिफ़ॉल्ट है)। डॉक्स विशेष रूप से उल्लेख करते हैं कि यह विंडोज एक्सप्लोरर में फ़ाइल के आइकन पर डबल-क्लिक करने जैसा है।

यह समाधान केवल विंडोज़ है।


धन्यवाद। मैंने उपलब्धता पर ध्यान नहीं दिया, क्योंकि डॉक्स ने इसे अंतिम पैराग्राफ में जोड़ दिया है। अधिकांश अन्य वर्गों में, उपलब्धता नोट की अपनी रेखा है।
DrBloodmoney

लिनक्स किसी कारण से, एक त्रुटि को बढ़ाने के बजाय, startfileफ़ंक्शन भी मौजूद नहीं है, जिसका अर्थ है कि उपयोगकर्ताओं को एक लापता फ़ंक्शन के बारे में भ्रमित करने वाला संदेश मिलेगा। इससे बचने के लिए आप प्लेटफ़ॉर्म की जाँच कर सकते हैं।
cz

39

बस पूर्णता के लिए (यह सवाल में नहीं था), xdg- ओपन लिनक्स पर ऐसा ही करेगा।


6
+1 आमतौर पर, उत्तरदाताओं को उन सवालों का जवाब नहीं देना चाहिए जो नहीं पूछे गए थे, लेकिन इस मामले में मुझे लगता है कि यह एसओ समुदाय के लिए समग्र रूप से बहुत ही प्रासंगिक और सहायक है।
डेमॉन्गोलम

यह देख रहा था
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
हुह, मुझे शुरुआत के बारे में पता नहीं था। यह अच्छा होगा यदि पायथन के मैक और लिनक्स संस्करण समान शब्दार्थ उठाए।
निक

3
प्रासंगिक अजगर बग: Bugs.python.org/issue3177 - एक अच्छा पैच प्रदान करते हैं, और यह स्वीकार किया जा सकता है =)
gnud

xuxg-linux के लिए ओपन कमांड
TheTechRobo36414519

21

यदि आपको एक हेयुरिस्टिक विधि का उपयोग करना है, तो आप विचार कर सकते हैं webbrowser
यह मानक पुस्तकालय है और इसके नाम के बावजूद भी यह फाइलें खोलने की कोशिश करेगा:

ध्यान दें कि कुछ प्लेटफार्मों पर, इस फ़ंक्शन का उपयोग करके फ़ाइल नाम खोलने की कोशिश कर रहा है, काम कर सकता है और ऑपरेटिंग सिस्टम के संबद्ध प्रोग्राम को शुरू कर सकता है। हालाँकि, यह न तो समर्थित है और न ही पोर्टेबल है। ( संदर्भ )

मैंने इस कोड की कोशिश की और इसने विंडोज 7 और उबंटू नेट्टी में ठीक काम किया:

import webbrowser
webbrowser.open("path_to_file")

Internet Explorer 8 का उपयोग करके यह कोड Windows XP Professional में भी ठीक काम करता है।


3
जहां तक ​​मैं बता सकता हूं, यह अब तक का सबसे अच्छा जवाब है। क्रॉस-प्लेटफ़ॉर्म लगता है और यह जांचने की आवश्यकता नहीं है कि ओएस, प्लेटफ़ॉर्म के उपयोग या आयात में कौन सा प्लेटफ़ॉर्म है।
बहुपत्नी

2
@jonathanrocher: मुझे स्रोत कोड में मैक समर्थन दिखाई देता है । यह open locationवहां उपयोग करता है जो कि काम करना चाहिए यदि आप एक वैध यूआरएल के रूप में रास्ता देते हैं।
jfs

1
macOS:import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
डैनियल स्प्रिंगर

3
docs.python.org/3/library/webbrowser.html#webbrowser.open "ध्यान दें कि कुछ प्लेटफार्मों पर, [webbrowser.open (url)] का उपयोग करके फ़ाइल नाम खोलने की कोशिश कर रहा है, ऑपरेटिंग सिस्टम से जुड़े प्रोग्राम को शुरू और काम कर सकता है। , यह न तो समर्थित है और न ही पोर्टेबल है। "
nyanpasu64

6

यदि आप subprocess.call()रास्ते पर जाना चाहते हैं , तो इसे विंडोज पर इस तरह दिखना चाहिए:

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विधि एन मापदंडों को ठीक से उद्धृत करता है, 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 )

एपीआई कॉल के साथ काम करने के लिए फ़ाइल मौजूद है।


1
एक अन्य समाधान यह है कि इसे उद्धरणों में एक शीर्षक दिया जाए, जैसेstart "Title" "C:\long path to\file.avi"
user3364825

3

मुझे बहुत देर हो गई है, लेकिन यहाँ विंडोज़ एपीआई का उपयोग करके एक समाधान है। यह हमेशा संबंधित एप्लिकेशन को खोलता है।

import ctypes

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

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

ढेर सारा जादू। पहला शून्य वर्तमान कार्यक्रम का hwnd है। शून्य हो सकता है। अन्य दो शून्य वैकल्पिक पैरामीटर (पैरामीटर और निर्देशिका) हैं। 5 == SW_SHOW, यह निर्दिष्ट करता है कि ऐप को कैसे निष्पादित किया जाए। अधिक जानकारी के लिए ShellExecute API डॉक्स पढ़ें ।


1
यह कैसे तुलना करता है os.startfile(file)?
JFS

2

मैक ओएस पर आप 'ओपन' कह सकते हैं

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

यह टेक्स्टएडिट के साथ फाइल को खोलेगा, या जो भी ऐप इस फाइल के लिए तयशुदा है


2

यदि आप Mac OS X पर फ़ाइल खोलने के लिए एप्लिकेशन निर्दिष्ट करना चाहते हैं, तो इसका उपयोग करें: os.system("open -a [app name] [file name]")


2

विंडोज 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))

2

os.startfile(path, 'open')विंडोज के तहत अच्छा है क्योंकि जब स्पेस निर्देशिका में मौजूद होते हैं, os.system('start', path_name)तो ऐप को सही ढंग से नहीं खोल सकता है और जब निर्देशिका में i18n मौजूद होता है, तो os.systemविंडोज में कंसोल के कोडेक में यूनिकोड को बदलने की आवश्यकता होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.