पायथन 3 में निष्पादन का एक विकल्प क्या है?


352

ऐसा लगता है कि वे पायथन 3 में सभी रद्द करने के लिए जल्दी से एक स्क्रिप्ट को लोड करने के लिए आसान तरीका है execfile()

क्या कोई स्पष्ट विकल्प है जो मुझे याद आ रहा है?


1
reloadimp.reload3.2 के बाद से वापस आ गया है ।
डगल

18
यदि आप पाइथन का उपयोग कर रहे हैं, तो आप IPython का उपयोग करते हुए पारस्परिक रूप से विचार करें: %run script_nameपाइथन के सभी संस्करण के साथ काम करता है।
माइकल

1
3.4 के बाद से impहै importlib (जो आयात किया जाना चाहिए): importlib.reload(mod_name)आयात और कार्यान्वित mod_name
पी। वॉर्मर

3
रनफाइल ("फ़ाइलनामें") में क्या गलत है?
मौसमी

1
धन्यवाद @ मूसर !! मैं ठीक से कार्यक्षमता की तलाश कर रहा था runfile()क्योंकि मुझे एक पायथन स्क्रिप्ट को चलाने की ज़रूरत थी जो अपने स्वयं के नामस्थान में निष्पादित होती है (जैसा कि कॉलिंग नाम स्थान पर निष्पादित करने का विरोध किया गया है )। मेरा आवेदन: विशेषता पथ sys.pathका उपयोग करके स्क्रिप्ट को निर्देशिका पथ में जोड़ें ( ) __file__विशेषता का उपयोग करते हुए : यदि हम execfile()पायथन 3 ( exec(open('file.py').read())) में सम्‍मिलित या इसके समतुल्य का उपयोग करते हैं , तो शामिल स्क्रिप्ट को कॉलिंग नेमस्पेस में चलाया जाता है और इस प्रकार कॉलिंग फ़ाइल नाम का __file__समाधान होता है ।
मस्तूरी

जवाबों:


389

प्रलेखन के अनुसार , के बजाय

execfile("./filename") 

उपयोग

exec(open("./filename").read())

देख:


54
किसी भी विचार है कि वे ऐसा क्यों करेंगे? यह पहले की तुलना में बहुत अधिक क्रिया है। इसके अलावा, यह मेरे लिए Python3.3 पर काम नहीं करता है। जब मैं निष्पादित करता हूं तो मुझे "ऐसी कोई फ़ाइल या निर्देशिका" नहीं मिलती है (खुली ('./ some_file')। पढ़ें ()। मैंने '.py' एक्सटेंशन को शामिल करने की कोशिश की है और साथ ही './' को भी छोड़ दिया है
JoeyC

25
कम तुच्छता से, यह अपवाद नहीं होने पर लाइन नंबर प्रदान नहीं करता है, जैसा कि निष्पादन योग्य ()।
केडीएन

35
आपको closeउस फ़ाइल को भी संभालना होगा। अजगर 2 से परिवर्तन को नापसंद करने का एक और कारण
रीब्स

3
@ आपको उस उदाहरण में फ़ाइल हैंडल को बंद करने की आवश्यकता नहीं है, यह स्वचालित रूप से किया जाएगा (कम से कम नियमित रूप से CPython में)
tiho

4
@ रेफ़र इन सीपीथॉन ऑब्जेक्ट्स कचरा-एकत्र किए जाते हैं जैसे ही उनकी संदर्भ संख्या 0 पर जाती है, केवल परिपत्र संदर्भ ही इसमें देरी कर सकते हैं ( stackoverflow.com/questions/9449489/… )। उस मामले में जो पढ़ने के बाद सही होना चाहिए () रिटर्न। और फ़ाइल ऑब्जेक्ट्स डिलीट होने पर बंद हो जाती हैं (NB: मुझे यह पता चलता है कि यह लिंक "हमेशा क्लोज़ फाइल्स" कहती है, जो वास्तव में सामान्य रूप से पालन करने के लिए अच्छा अभ्यास है)
tiho

219

आप बस फ़ाइल को पढ़ने और कोड को स्वयं निष्पादित करने वाले हैं। 2to3 वर्तमान की जगह

execfile("somefile.py", global_vars, local_vars)

जैसा

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(संकलन कॉल की कड़ाई से आवश्यकता नहीं है, लेकिन यह फ़ाइल नाम को कोड ऑब्जेक्ट के साथ जोड़ देता है, जिससे डीबग करना थोड़ा आसान हो जाता है)

देख:


3
यह मेरे लिए काम करता है। हालाँकि, मैंने देखा कि आपने स्थानीय और वैश्विक तर्कों को गलत क्रम में लिखा है। यह वास्तव में है: निष्पादन (ऑब्जेक्ट [, ग्लोबल्स [, स्थानीय लोग]])। बेशक, अगर आपके पास तर्क मूल में फ़्लॉप हो गए थे, तो 2to3 आपके द्वारा कहा गया वास्तव में उत्पादन करेगा। :)
नाथन श्लीट-सैंडर्स

3
यह जानकर प्रसन्नता हुई कि, यदि आप global_vars और local_vars को छोड़ सकते हैं, तो यहाँ python3 प्रतिस्थापन python2 के तहत भी काम करता है। हालांकि execpython2 में एक बयान है, exec(code)काम करता है क्योंकि पार्न्स को केवल अनदेखा किया जाता है।
मध्याह्न

2
संकलन का उपयोग करने के लिए +1। मेरा "somefile.py"निहित inspect.getsourcefile(lambda _: None)जो संकलन के बिना विफल हो रहा था, क्योंकि inspectमॉड्यूल यह निर्धारित नहीं कर सकता था कि कोड कहां से आ रहा था।
ArtOfWarfare

16
यह वास्तव में बदसूरत है। किसी भी विचार क्यों वे 3.x में निष्पादन () से छुटकारा पा लिया? एग्जीक्यूटिव ने कमांडलाइन आर्ग को पास करना भी आसान बना दिया।
एनाजोडियल

3
open("somefile.py")यदि somefile.pyकोई वर्ण एन्कोडिंग से भिन्न का उपयोग करता है तो गलत हो सकता है locale.getpreferredencoding()tokenize.open()इसके बजाय इस्तेमाल किया जा सकता है।
jfs

73

जबकि exec(open("filename").read())अक्सर एक विकल्प के रूप में दिया जाता है execfile("filename"), यह महत्वपूर्ण विवरणों को याद करता है जो execfileसमर्थन करता है।

Python3.x के लिए निम्न फ़ंक्शन उतना ही करीब है जितना कि किसी फ़ाइल को सीधे निष्पादित करने के समान व्यवहार हो सकता है। जो चल रहा है python /path/to/somefile.py

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), globals, locals)

# execute the file
execfile("/path/to/somefile.py")

टिप्पणियाँ:

  • एन्कोडिंग मुद्दों से बचने के लिए बाइनरी रीडिंग का उपयोग करता है
  • फ़ाइल को बंद करने की गारंटी (Python3.x इस बारे में चेतावनी देती है)
  • परिभाषित करता है __main__, कुछ स्क्रिप्ट इस बात पर निर्भर करती हैं कि वे मॉड्यूल के रूप में लोड कर रहे हैं या नहीं।if __name__ == "__main__"
  • सेटिंग __file__अपवाद संदेशों के लिए अच्छे हैं और कुछ स्क्रिप्ट __file__उनके सापेक्ष अन्य फ़ाइलों के पथ प्राप्त करने के लिए उपयोग करते हैं।
  • वैकल्पिक ग्लोबल्स और स्थानीय तर्क देता है, उन्हें इन-प्लेस में संशोधित execfileकरता है - ताकि आप चलने के बाद चर को पढ़कर परिभाषित किसी भी चर तक पहुंच सकें।

  • Python2 के विपरीत execfileयह डिफ़ॉल्ट रूप से वर्तमान नाम स्थान को संशोधित नहीं करता है । उसके लिए आपको स्पष्ट रूप से globals()& में पास होना होगा locals()


68

जैसा कि हाल ही में अजगर-देव मेलिंगलिस्ट पर सुझाव दिया गया था , रनपी मॉड्यूल एक व्यवहार्य विकल्प हो सकता है। उस संदेश से उद्धरण:

https://docs.python.org/3/library/runpy.html#runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

इसमें सूक्ष्म अंतर हैं execfile:

  • run_pathहमेशा एक नया नामस्थान बनाता है। यह कोड को एक मॉड्यूल के रूप में निष्पादित करता है, इसलिए ग्लोबल्स और स्थानीय लोगों के बीच कोई अंतर नहीं है (यही वजह है कि केवल एक init_globalsतर्क है)। ग्लोबल्स वापस कर दिए जाते हैं।

    execfileवर्तमान नाम स्थान या दिए गए नाम स्थान में निष्पादित। के शब्दार्थ localsऔर globals, यदि दिए गए हैं, तो एक वर्ग परिभाषा के अंदर स्थानीय और ग्लोबल्स के समान थे।

  • run_path न केवल फाइलों को निष्पादित कर सकते हैं, बल्कि अंडे और निर्देशिकाएं (विवरण के लिए इसके प्रलेखन को देखें)।


1
किसी कारण के लिए, यह स्क्रीन को बहुत सारी जानकारी के लिए आउटपुट करता है जिसे एनाकोंडा पायथन 3 में प्रिंट (' बिल्डिंस ' ) के लिए नहीं कहा गया था । क्या इसे बंद करने का कोई तरीका है ताकि केवल वह जानकारी जिसे मैं प्रिंट के साथ आउटपुट करता हूं () कल्पना हो?
जॉन डॉन

क्या वर्तमान कार्यक्षेत्र में उन सभी चर को प्राप्त करना संभव है, जिनके बजाय उन सभी को संग्रहीत किया जा रहा है file_globals? यह file_globals['...']हर चर के लिए टाइप करने के लिए बचा होगा ।
एड्रियन

1
"इसके अलावा, निष्पादित कोड द्वारा परिभाषित किसी भी फ़ंक्शन और कक्षाएं सही ढंग से काम करने की गारंटी नहीं हैं, जब एक रफ फ़ंक्शन वापस आ गया है।" वर्थ नोटिंग, आपके उपयोग के मामले पर निर्भर करता है
19 '

@ Adriaan निष्पादित "ग्लोबल्स ()। अद्यतन (file_globals)"। व्यक्तिगत रूप से मुझे यह समाधान सबसे अच्छा लगता है क्योंकि मैं वर्तमान कार्यक्षेत्र को अपडेट करने का निर्णय लेने से पहले संभवतः त्रुटियों को पकड़ सकता हूं।
रॉन कमिंसकी

@nodakai जानकारी के लिए धन्यवाद, मुझे वह याद आया। कभी भी इस तरह की कोई समस्या नहीं थी, मुझे आश्चर्य है कि इस बंद को स्थापित करने की संभावना क्या है।
रॉन कमिंसकी

21

यह बेहतर है, क्योंकि यह कॉलर से ग्लोबल्स और लोकल लेता है:

import sys
def execfile(filename, globals=None, locals=None):
    if globals is None:
        globals = sys._getframe(1).f_globals
    if locals is None:
        locals = sys._getframe(1).f_locals
    with open(filename, "r") as fh:
        exec(fh.read()+"\n", globals, locals)

दरअसल, यह py2 के करीब है execfile। यह भी मेरे लिए काम किया जब pytests का उपयोग कर जहां अन्य समाधान ऊपर पोस्ट विफल रहा। धन्यवाद! :)
बोरिएल

17

आप अपना कार्य लिख सकते हैं:

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

यदि आप वास्तव में जरूरत है ...


1
-1: निष्पादन क़ानून इस तरह से काम नहीं करता है। अजगर के किसी भी संस्करण में कोड नहीं चलता है।
nosklo

6
-1: डिफॉल्ट पैरामीटर मानों का मूल्यांकन फंक्शन डेफिनिशन टाइम पर किया जाता है, जो दोनों को बनाता है globalsऔर कॉल करने वाले की ग्लोबल और लोकल नेमस्पेस की बजाय localsमॉड्यूल के ग्लोबल नेमस्पेस को इंगित execfile()करता है। सही दृष्टिकोण Noneडिफ़ॉल्ट मूल्य के रूप में उपयोग करना और inspectमॉड्यूल की आत्मनिरीक्षण क्षमताओं के माध्यम से कॉलर के ग्लोबल्स और स्थानीय लोगों को निर्धारित करना है ।
स्वेन मार्नाच

12

यदि आप जिस स्क्रिप्ट को लोड करना चाहते हैं, वह उसी निर्देशिका में है जिसे आप चलाते हैं, तो शायद "आयात" काम करेगा?

यदि आपको कोड को अंतर्निहित फ़ंक्शन __ import__ को गतिशील रूप से आयात करने की आवश्यकता है और मॉड्यूल छोटा सा दिखने योग्य है।

>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'

test.py:

def run():
        return "Hello world!"

यदि आप पायथन 3.1 या उसके बाद का उपयोग कर रहे हैं, तो आपको भी आयात पर एक नज़र डालनी चाहिए


यह मेरे लिए सही उत्तर था। यह ब्लॉग importlib dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805
निक ब्रैडी

9

यहाँ मेरे पास क्या है ( fileपहले से ही दोनों उदाहरणों में स्रोत कोड के साथ फ़ाइल को पथ को सौंपा गया है):

execfile(file)

यहाँ मैंने इसे किसके साथ प्रतिस्थापित किया है:

exec(compile(open(file).read(), file, 'exec'))

मेरा पसंदीदा हिस्सा: दूसरा संस्करण पायथन 2 और 3 दोनों में ठीक काम करता है, जिसका अर्थ है कि संस्करण पर निर्भर तर्क में जोड़ना आवश्यक नहीं है।


5

ध्यान दें कि यदि आप PEP-263 एन्कोडिंग घोषणाओं का उपयोग कर रहे हैं जो ascii या utf-8 नहीं हैं तो उपरोक्त पैटर्न विफल हो जाएगा। आपको डेटा के एन्कोडिंग को खोजने की जरूरत है, और इसे निष्पादित करने से पहले इसे सही तरीके से एनकोड करें ()।

class python3Execfile(object):
    def _get_file_encoding(self, filename):
        with open(filename, 'rb') as fp:
            try:
                return tokenize.detect_encoding(fp.readline)[0]
            except SyntaxError:
                return "utf-8"

    def my_execfile(filename):
        globals['__file__'] = filename
        with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp:
            contents = fp.read()
        if not contents.endswith("\n"):
            # http://bugs.python.org/issue10204
            contents += "\n"
        exec(contents, globals, globals)

3
"उपरोक्त पैटर्न" क्या है? StackOverflow पर अन्य पोस्ट का जिक्र करते समय लिंक का उपयोग करें। "ऊपर" जैसे सापेक्ष स्थिति शब्द काम नहीं करते हैं, क्योंकि उत्तर छाँटने के 3 अलग-अलग तरीके हैं (वोट से, तिथि, या गतिविधि से) और सबसे आम एक (वोट से) अस्थिर है। समय के साथ आपकी पोस्ट और आपके आस-पास के पोस्ट अलग-अलग स्कोर के साथ समाप्त हो जाएंगे, जिसका अर्थ है कि उन्हें फिर से व्यवस्थित किया जाएगा और इस तरह की तुलना कम उपयोगी होगी।
आर्टऑफवर्फ

बहुत अच्छी बात है। और यह देखते हुए कि मैंने यह उत्तर लगभग छह महीने पहले लिखा था, मुझे लगता है कि "उपरोक्त पैटर्न" से मेरा मतलब है stackoverflow.com/a/2849077/165082 (जो दुर्भाग्य से आपको हल करने के लिए क्लिक करना होगा), या बेहतर अभी भी नोआम का जवाब है:
एरिक

2
आम तौर पर जब मैं अपने उत्तर में से एक ही प्रश्न के अन्य उत्तरों को संदर्भित करना चाहता हूं, तो मैं "Noam's Answer" टाइप करता हूं (उदाहरण के लिए) और उस पाठ को उस उत्तर से लिंक करता हूं जिसका मैं उल्लेख कर रहा हूं, बस इस मामले में जवाब से अलग हो जाता है भविष्य में उपयोगकर्ता, IE, क्योंकि उपयोगकर्ता अपना खाता नाम बदल देता है या पोस्ट एक सांप्रदायिक विकी बन जाता है क्योंकि इस पर बहुत सारे संपादन किए गए हैं।
आर्टऑफवर्फ

उत्तर के पोस्टर के नाम को छोड़कर आपको किसी पोस्ट के साथ एक विशिष्ट "उत्तर" के लिए URL कैसे मिलता है?
DevPlayer

स्रोत देखें और आईडी प्राप्त करें। उदाहरण के लिए, आपका प्रश्न stackoverflow.com/questions/436198/… होगा । मैं एक बेहतर तरीके के लिए सभी हूं, लेकिन जब मैं टिप्पणी के पास मंडराता हूं तो कुछ भी नहीं देखता हूं
एरिक

4

इसके अलावा, जबकि शुद्ध पायथन समाधान नहीं है, यदि आप IPython का उपयोग कर रहे हैं (जैसा कि आप शायद वैसे भी करना चाहिए), आप कर सकते हैं:

%run /path/to/filename.py

जो समान रूप से आसान है।


1

मैं यहाँ सिर्फ एक नौसिखिया हूँ तो शायद यह शुद्ध भाग्य है अगर मुझे यह मिला:

कमांड के साथ दुभाषिए प्रॉम्प्ट >>> से स्क्रिप्ट चलाने की कोशिश करने के बाद

    execfile('filename.py')

जिसके लिए मुझे "NameError: name 'execfile' परिभाषित नहीं किया गया है" मैंने बहुत बुनियादी कोशिश की

    import filename

यह अच्छी तरह से काम किया :-)

मुझे उम्मीद है कि यह मददगार हो सकता है और आप सभी को महान संकेत, उदाहरण और उन सभी कोड के मास्टरली टिप्पणी के लिए धन्यवाद जो नए लोगों के लिए एक महान प्रेरणा हैं!

मैं Ubuntu 16.014 LTS x64 का उपयोग करता हूं। पायथन 3.5.2 (डिफ़ॉल्ट, 17 नवंबर 2016, 17:05:23) [जीसीसी 5.4.0 20160609] लिनक्स पर


0

मेरे लिए, सबसे साफ तरीका यह है importlibकि फ़ाइल को एक मॉड्यूल के रूप में प्रयोग करके आयात करें, जैसे:

from importlib import util

def load_file(name, path):
    spec = util.spec_from_file_location(name, path)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

उदाहरण का उपयोग करें

चलो एक फ़ाइल है foo.py:

print('i got imported')
def hello():
    print('hello from foo')

अब इसे सामान्य मॉड्यूल की तरह आयात और उपयोग करें:

>>> foo = load_file('foo', './foo.py')
i got imported
>>> foo.hello()
hello from foo

मैं इस तकनीक को प्रत्यक्ष दृष्टिकोणों की तरह पसंद exec(open(...))करता हूं क्योंकि यह आपके नाम स्थान को अव्यवस्थित नहीं करता है या अनावश्यक रूप से गड़बड़ करता है $PATH

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