2012-09-04 15 views
13

पायथन सी एपीआई फ़ंक्शन PyEval_EvalCode चलिए आप संकलित पायथन कोड निष्पादित करते हैं। मैं पाइथन कोड के ब्लॉक को निष्पादित करना चाहता हूं जैसे कि यह फ़ंक्शन के दायरे में निष्पादित कर रहा था, ताकि उसके पास स्थानीय चर का अपना शब्दकोश हो जो वैश्विक स्थिति को प्रभावित न करे।सी पायथन: एक संदर्भ के भीतर पाइथन कोड चलाना

यह आसान करने के लिए पर्याप्त लगता है के बाद से PyEval_EvalCode आप एक वैश्विक और स्थानीय शब्दकोश प्रदान कर सकते हैं:

PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)

समस्या मैं कैसे अजगर चर नाम की खोज करता है के साथ क्या करना है में चलाने। निम्नलिखित कोड पर विचार करें, कि मैं PyEval_EvalCode साथ निष्पादित करें:

myvar = 300 
def func(): 
    return myvar 

func() 

यह सरल कोड वास्तव में, एक त्रुटि को जन्म देती है क्योंकि अजगर चर myvarfunc के भीतर से खोजने में असमर्थ है। भले ही myvar बाहरी क्षेत्र में स्थानीय शब्दकोश में है, पाइथन इसे आंतरिक क्षेत्र में स्थानीय शब्दकोश में कॉपी नहीं करता है।

जब भी अजगर एक चर नाम की खोज करता है पहले यह locals की जाँच करता है, तो यह globals की जाँच करता है, और अंत में यह builtins की जाँच करता है,: इस का कारण इस प्रकार है। मॉड्यूल स्कोप, locals और globals समान शब्दकोश ऑब्जेक्ट हैं। तो मॉड्यूल स्कोप पर x = 5 कथन locals शब्दकोश में रखेगा, जो globals शब्दकोश भी है। अब, मॉड्यूल स्कोप पर परिभाषित एक फ़ंक्शन जिसे x को देखने की आवश्यकता है x फ़ंक्शन-स्कोप locals के भीतर नहीं मिलेगा, क्योंकि पायथन मॉड्यूल-स्कोप स्थानीय लोगों को फ़ंक्शन-स्कोप स्थानीय में कॉपी नहीं करता है। लेकिन यह सामान्य रूप से कोई समस्या नहीं है, क्योंकि यह globals में पा सकता है।

x = 5 
def foo(): 
    print(x) # This works because 'x' in globals() == True 

यह केवल के साथ नेस्टेड कार्यों कि अजगर भीतरी गुंजाइश स्थानीय लोगों में बाहरी-गुंजाइश स्थानीय लोगों की नकल करने लगता है,। (यह भी तो lazily ऐसा करने के लिए, केवल अगर वे भीतरी दायरे के भीतर की जरूरत है लगता है।)

def foo(): 
    x = 5 
    def bar(): 
     print(x) # Now 'x' in locals() == True 
    bar() 


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

लेकिन मेरे मामले में, मैं वैश्विक शब्दकोश और स्थानीय शब्दकोश को वही नहीं चाहता हूं। इसलिए मुझे पाइथन दुभाषिया को बताने के लिए कुछ तरीका चाहिए कि मैं फ़ंक्शन स्कोप पर कोड निष्पादित कर रहा हूं। क्या ऐसा करने का कोई तरीका है? मैंने PyCompileFlags पर साथ ही PyEval_EvalCodeEx पर अतिरिक्त तर्कों को देखा और इसे करने का कोई तरीका नहीं मिला।

उत्तर

3

पायथन वास्तव में बाहरी-स्कोप स्थानीय लोगों को आंतरिक-स्कोप स्थानीय लोगों में कॉपी नहीं करता है; locals के लिए प्रलेखन:

नि: शुल्क चर स्थानीय लोगों द्वारा वापस लौटाए जाते हैं() जब इसे फ़ंक्शन ब्लॉक में कहा जाता है, लेकिन कक्षा ब्लॉक में नहीं।

यहां "मुक्त" चर किसी नेस्टेड फ़ंक्शन द्वारा बंद चर को संदर्भित करता है। यह एक महत्वपूर्ण भेद है।

अपनी स्थिति के लिए सबसे आसान ठीक globals और locals रूप ही dict वस्तु पारित करने के लिए बस है: अन्यथा

code = """ 
myvar = 300 
def func(): 
    return myvar 

func() 
""" 
d = {} 
eval(compile(code, "<str>", "exec"), d, d) 

, आप एक समारोह में अपने कोड लपेट और संकलित ऑब्जेक्ट से यह निकाल सकते हैं:

s = 'def outer():\n ' + '\n '.join(code.strip().split('\n')) 
exec(compile(s, '<str>', 'exec').co_consts[0], {}, {}) 
+0

@ चैनल 72 ऊपर देखें। – ecatmur

संबंधित मुद्दे