मैं पायथन में पायथन कोड युक्त स्ट्रिंग को कैसे निष्पादित करूं?


357

मैं पायथन में पायथन कोड युक्त स्ट्रिंग को कैसे निष्पादित करूं?


5
निष्पक्ष होने के लिए, अन्य प्रश्न के विपरीत, यह एक डुप्लिकेट नहीं है। और अन्य लोगों ने इससे कई अधिक बुनियादी प्रश्न पोस्ट किए हैं।
DNS

8
सही जवाब, ज़ाहिर है, लगभग हमेशा "नहीं!" है।
बोबिन्स

23
@S। लोट: हाल ही में अक्सर पूछे जाने वाले प्रश्न नहीं पढ़े हैं? "यह आपके अपने प्रोग्रामिंग प्रश्न को पूछने और उत्तर देने के लिए पूरी तरह से ठीक है, लेकिन आप खतरे में हैं इसका नाटक करें: इसे प्रश्न के रूप में वाक्यांश दें"। यह कोई बुरा सवाल नहीं है। +1
डेविन जीनपिएरे

49
@ S.Lott: आप नहीं। आप की जरूरत नहीं है। यदि प्रश्न पहले से ही साइट पर नहीं है, तो यह उचित खेल है (एफएक्यू के अनुसार, जैसा कि पहले ही बताया गया है)। बस हर सवाल का जवाब दें, हालांकि ओपी को मदद की जरूरत है। वे नहीं कर सकते हैं, लेकिन अगले आदमी को जो अपने सवाल पढ़ता है शायद होगा। बस मेरे 2 सेंट।
छिपकली

1
आप सभी को यह नहीं करने के लिए कह रहा हूं: मेरे पास एक ऐसा मामला है जहां मुझे इसकी आवश्यकता है। इसमें वितरित प्रसंस्करण शामिल है।
सूदो

जवाबों:


331

बयानों के लिए, exec(string)(पायथन 2/3) या exec string(पायथन 2) का उपयोग करें:

>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world

जब आपको अभिव्यक्ति के मूल्य की आवश्यकता हो, तो उपयोग करें eval(string):

>>> x = eval("2+2")
>>> x
4

हालांकि, पहला कदम खुद से पूछना चाहिए कि क्या आपको वास्तव में जरूरत है। निष्पादन कोड आम तौर पर अंतिम उपाय की स्थिति होना चाहिए: यदि यह उपयोगकर्ता-दर्ज कोड हो सकता है, तो यह धीमा, बदसूरत और खतरनाक है। आपको हमेशा पहले विकल्पों को देखना चाहिए, जैसे कि उच्च क्रम वाले कार्य, यह देखने के लिए कि क्या ये आपकी आवश्यकताओं को बेहतर तरीके से पूरा कर सकते हैं।


1
लेकिन 'निष्पादित' द्वारा निष्पादित कोड के दायरे के बारे में कैसे? क्या यह नेस्टेड है?
जॉन्डिंघम

21
एक सामान्य मामला जहां कोई 'निष्पादन' का उपयोग करना चाहता है, if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42आदि कुछ ऐसा है , जिसे वे तब लिख सकते हैं exec ("x.%s = 42" % s)। इस सामान्य मामले के लिए (जहां आपको केवल किसी ऑब्जेक्ट की विशेषता को एक्सेस करने की आवश्यकता होती है जो एक स्ट्रिंग में संग्रहीत होती है), बहुत तेज़, क्लीनर और सुरक्षित फ़ंक्शन है getattr: बस getattr(x, s) = 42एक ही चीज़ का मतलब लिखने के लिए लिखें ।
श्रीवत्सआर

5
अजगर दुभाषिया की तुलना में किसी भी धीमे को कैसे निष्पादित किया जाता है?
संकट स्ट्रींगफेलो

6
@ श्रीवत्सआर क्या आपका मतलब नहीं है setattr(x, s, 42)? मैंने कोशिश की getattr(x, 2) = 42और इसके साथ असफल रहाcan't assign to function call: <string>, line 1
टान्नर सेमराद

6
@ टैनर: हम्म। हाँ वास्तव setattr(x, s, 42)में सही वाक्यविन्यास है। हैरानी की बात यह है कि उस त्रुटि को पकड़ने में इतनी देर लगी। वैसे भी, मुद्दा यह है कि getattrऔर setattrएक विकल्प है execजब आप चाहते हैं कि एक मनमाना सदस्य प्राप्त करना है, स्ट्रिंग द्वारा देखा गया।
श्रीवत्सआर

68

उदाहरण में एक स्ट्रिंग को निष्पादन फ़ंक्शन का उपयोग करके कोड के रूप में निष्पादित किया जाता है।

import sys
import StringIO

# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()

code = """
def f(x):
    x = x + 1
    return x

print 'This is my output.'
"""

# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr

exec code

# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

print f(4)

s = codeErr.getvalue()

print "error:\n%s\n" % s

s = codeOut.getvalue()

print "output:\n%s" % s

codeOut.close()
codeErr.close()

1
स्ट्रैडआउट और स्ट्रैडर को स्वैप करना जैसे मुझे बहुत परेशान करता है। ऐसा लगता है कि यह भारी सुरक्षा समस्याओं का कारण बन सकता है। वहाँ एक तरीका है कि चारों ओर है?
नारकोलापर

1
@Narcolapser आपको अधिक उपयोग करने execसे संबंधित होना चाहिए (जब तक आपको पता न हो कि कोड स्ट्रिंग किसी विश्वसनीय स्रोत से आता है)।
ब्रूनो डेथिलियर्स 17

27

evalऔर execसही समाधान हैं, और उनका उपयोग सुरक्षित रूप से किया जा सकता है तरीके से है।

जैसा कि पायथन के संदर्भ मैनुअल में चर्चा की गई है और इस ट्यूटोरियल में स्पष्ट रूप से समझाया गया है , evalऔरexec फ़ंक्शन दो अतिरिक्त पैरामीटर लेते हैं जो उपयोगकर्ता को यह निर्दिष्ट करने की अनुमति देते हैं कि वैश्विक और स्थानीय फ़ंक्शन और चर उपलब्ध हैं।

उदाहरण के लिए:

public_variable = 10

private_variable = 2

def public_function():
    return "public information"

def private_function():
    return "super sensitive information"

# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len

>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12

>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined

>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters

>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined

संक्षेप में आप उन नामों को परिभाषित कर रहे हैं जिनमें कोड निष्पादित किया जाएगा।


9
Eval को सुरक्षित बनाना संभव नहीं है: Eval वास्तव में खतरनाक है । यदि आप मुझसे कोड लेते हैं और इसे निकालते हैं, तो मैं आपके पायथन प्रोग्राम को जब्त कर सकता हूं। खेल खत्म।
नेड बैचेल्ड

3
@ v.oddou मैं एलन के बयान पर प्रतिक्रिया दे रहा था, "निष्कासन और क्रियान्वयन .. सुरक्षित तरीके से किया जा सकता है।" यह गलत है। अगर किसी ने कहा, "बैश को सुरक्षित तरीके से इस्तेमाल किया जा सकता है," तो यह भी गलत होगा। बैश खतरनाक है। यह एक आवश्यक खतरा है, लेकिन फिर भी खतरनाक है। यह दावा करना कि eval को सुरक्षित बनाया जा सकता है, गलत है।
नेड बाचेल्डर

1
@NedBatchelder वास्तव में हाँ। और आपके द्वारा इंगित लिंक अच्छी सामग्री है। शक्ति के साथ जिम्मेदारी आती है, इसलिए बिंदु को स्पष्ट रूप से विकसित होने की संभावित शक्ति के बारे में पता होना चाहिए। और अगर हम उस शक्ति = खतरे को तय करते हैं।
v.oddou

3
@NedBatchelder पायथन में लिखे गए कोड के कई टुकड़े खतरनाक भी हो सकते हैं, लेकिन आप ऐसा क्यों मान रहे हैं evalया execइसका उपयोग करने का इरादा है exec(input("Type what you want"))? ऐसे कई मामले हैं जहां एक कार्यक्रम एक संगणना के परिणामस्वरूप एक प्रक्रिया या कार्य लिख सकता है; परिणामी फ़ंक्शंस एक अच्छे और अच्छी तरह से लिखे गए प्रोग्राम के किसी भी अन्य भाग के रूप में सुरक्षित और तेज़ (एक बार मूल्यांकन किए जाने वाले) होंगे। एक असुरक्षित कार्यक्रम युक्त एक असुरक्षित कार्यक्रम execसे अधिक खतरनाक नहीं है जो खुद को नुकसान पहुंचाता है क्योंकि execयह कार्यक्रम को कोई नया विशेषाधिकार नहीं देता है।
थॉमस बरुचेल

1
@ThomasBaruchel फिर से, मेरी बात इस धारणा का मुकाबला करने के लिए है कि eval या exec को सुरक्षित बनाया जा सकता है। विशेष रूप से, यह उत्तर दावा करता है कि ग्लोबल्स और स्थानीय लोगों को नियंत्रित करने से उन्हें सुरक्षित रूप से उपयोग करना संभव होगा। वह झूठा है। किसी भी समय आप निष्पादन और eval का उपयोग करते हैं, आपको ठीक से जानना होगा कि किस कोड को निष्पादित किया जा रहा है। यदि आप नहीं करते हैं, तो आप खतरनाक ऑपरेशन के लिए खुले हैं।
नेड बैचेल्ड

21

याद रखें कि संस्करण 3 execसे एक फ़ंक्शन है!
इसलिए हमेशा exec(mystring)इसके बजाय उपयोग करें exec mystring


11

eval()सिर्फ अभिव्यक्ति के लिए है, जबकि eval('x+1')काम करता है, eval('x=1')उदाहरण के लिए काम नहीं करेगा। उस मामले में, इसका उपयोग करना बेहतर है exec, या इससे भी बेहतर: बेहतर समाधान खोजने की कोशिश करें :)


11

बचें exec औरeval

का उपयोग कर execऔरevalपाइथन का उस पर अत्यधिक प्रभाव पड़ता है।

बेहतर विकल्प हैं

शीर्ष उत्तर (जोर मेरा) से:

बयानों के लिए, का उपयोग करें exec

जब आपको अभिव्यक्ति के मूल्य की आवश्यकता हो, तो उपयोग करें eval

हालांकि, पहला कदम खुद से पूछना चाहिए कि क्या आपको वास्तव में जरूरत है। निष्पादन कोड आम तौर पर अंतिम उपाय की स्थिति होना चाहिए : यदि यह उपयोगकर्ता-दर्ज कोड हो सकता है, तो यह धीमा, बदसूरत और खतरनाक है। आपको हमेशा पहले विकल्पों को देखना चाहिए , जैसे कि उच्च क्रम वाले कार्य , यह देखने के लिए कि क्या ये आपकी आवश्यकताओं को बेहतर तरीके से पूरा कर सकते हैं।

से वैकल्पिक करने के लिए कार्यकारी / eval?

स्ट्रिंग्स में नामों के साथ वेरिएबल्स का मान सेट करें और प्राप्त करें

[जबकि eval] काम करेगा, यह आमतौर पर चर नाम का उपयोग करने की सलाह नहीं दी जाती है जो प्रोग्राम के लिए एक अर्थ है।

इसके बजाय, एक तानाशाही का बेहतर इस्तेमाल करें।

यह मुहावरेदार नहीं है

से http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (जोर मेरा)

पायथन PHP नहीं है

पायथन मुहावरों को दरकिनार करने की कोशिश न करें क्योंकि कुछ अन्य भाषा इसे अलग तरह से करती है। नामस्थान एक कारण के लिए पायथन में हैं और सिर्फ इसलिए कि यह आपको उपकरण देता है execइसका मतलब यह नहीं है कि आपको उस उपकरण का उपयोग करना चाहिए।

यह खतरनाक है

से http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (जोर मेरा)

तो eval सुरक्षित नहीं है, भले ही आप सभी globals और buildins को हटा दें!

इन सभी के निष्कासन () की सुरक्षा के प्रयासों के साथ समस्या यह है कि वे अश्वेत हैं । वे स्पष्ट रूप से उन चीजों को हटाते हैं जो खतरनाक हो सकते हैं। यह एक हारी हुई लड़ाई है क्योंकि अगर सूची से सिर्फ एक आइटम बचा है, तो आप सिस्टम पर हमला कर सकते हैं

तो क्या eval को सुरक्षित बनाया जा सकता है? बताना कठिन है। इस बिंदु पर, मेरा सबसे अच्छा अनुमान है कि यदि आप किसी भी डबल अंडरस्कोर का उपयोग नहीं कर सकते हैं, तो आप कोई नुकसान नहीं कर सकते हैं, इसलिए हो सकता है कि यदि आप डबल अंडरस्कोर के साथ किसी भी स्ट्रिंग को बाहर कर दें तो आप सुरक्षित हैं। शायद...

इसे पढ़ना और समझना कठिन है

से http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (जोर मेरा):

सबसे पहले, execयह आपके कोड को पढ़ने के लिए मनुष्य के लिए कठिन बनाता है । क्या हो रहा है, यह जानने के लिए, मुझे आपका कोड नहीं पढ़ना है, मुझे आपका कोड पढ़ना है, यह पता लगाना है कि यह किस स्ट्रिंग को उत्पन्न करने वाला है, फिर उस वर्चुअल कोड को पढ़ें। इसलिए, यदि आप एक टीम पर काम कर रहे हैं, या ओपन सोर्स सॉफ्टवेयर प्रकाशित कर रहे हैं, या स्टैकऑवरफ्लो जैसी कहीं मदद मांग रहे हैं, तो आप अन्य लोगों के लिए आपकी मदद करना कठिन बना रहे हैं। और अगर कोई मौका है कि आप अब से 6 महीने पहले इस कोड पर डिबगिंग या विस्तार करने जा रहे हैं, तो आप इसे सीधे अपने लिए कठिन बना रहे हैं।


"मेरा सबसे अच्छा अनुमान है कि यदि आप किसी भी डबल अंडरस्कोर का उपयोग नहीं कर सकते हैं तो आप कोई नुकसान नहीं कर सकते हैं" - आप डबल अंडरस्कोर वाले स्ट्रिंग का निर्माण कर सकते हैं, और फिर उस स्ट्रिंग को eval कह सकते हैं।
स्टेनली बक

अच्छी सलाह, जब तक आप एक कोड जनरेटर, या नौकरी धावक या समान लिख रहे हैं ... जो कि यहां ज्यादातर लोग शायद कर रहे हैं।
एरिक एरोनिटी

मुझे एक कॉन्फ़िगर-फ़ाइल ( cfg.yaml): reldir : ../my/dir/ और से एक सापेक्ष पथ आयात करना होगा reldir = cfg[reldir]। हालाँकि, यह अजगर कोड विंडोज और लिनक्स दोनों पर चलेगा, मुझे अलग-अलग ऑपरेटिंग सिस्टम पथ डिवाइडर में समायोजित करने के लिए इसकी आवश्यकता है; भी\\ या /। इसलिए मैं reldir : os.path.join('..','my','dir')config फाइल में उपयोग करता हूं । लेकिन इससे केवल reldirइस शाब्दिक स्ट्रिंग का मूल्यांकन किया जा रहा है, इसलिए मैं एक फ़ाइल नहीं खोल सकता reldir। आपका कोई सुझाव है?
मेरी। पी

9

आप निम्नलिखित IDLE सत्र के साथ, निष्पादन का उपयोग करते हुए निष्पादन कोड पूरा करते हैं:

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']

4

1
यह सामान्य अजगर में काम नहीं करता है। कम से कम अजगर में नहीं 3.
थॉमस अहले

6

जैसा कि दूसरों ने उल्लेख किया है, यह "निष्पादित" है।

लेकिन, यदि आपके कोड में वैरिएबल हैं, तो आप इसे एक्सेस करने के लिए "ग्लोबल" का उपयोग कर सकते हैं, साथ ही कंपाइलर को रोकने के लिए निम्नलिखित त्रुटि उठा सकते हैं:

NameError: नाम 'p_variable' परिभाषित नहीं है

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)


4

यह ध्यान देने योग्य बात है, कि execभाई मौजूद है execfileअगर आप एक अजगर फ़ाइल को कॉल करना चाहते हैं। यह कभी-कभी अच्छा होता है यदि आप किसी तीसरे पक्ष के पैकेज में काम कर रहे हैं जिसमें भयानक आईडीई शामिल है और आप उनके पैकेज के बाहर कोड करना चाहते हैं।

उदाहरण:

execfile('/path/to/source.py)'

या:

exec(open("/path/to/source.py").read())


3

की जाँच करें eval :

x = 1
print eval('x+1')
->2

10
Eval () कथनों को निष्पादित नहीं करता है।
रिका

1

मैंने काफी कुछ करने की कोशिश की, लेकिन केवल एक चीज जो निम्नलिखित थी:

temp_dict = {}
exec("temp_dict['val'] = 10") 
print(temp_dict['val'])

उत्पादन:

10


0

सबसे तार्किक समाधान बिल्ट-इन eval () फ़ंक्शन का उपयोग करना होगा। एक सॉल्यूशन उस स्ट्रिंग को एक अस्थायी पायथन फ़ाइल में लिखना और उसे निष्पादित करना है।


0

ठीक है .. मुझे पता है कि यह वास्तव में एक जवाब नहीं है, लेकिन संभवतः लोगों के लिए एक नोट है जो मैं था। मैं विभिन्न उपयोगकर्ताओं / ग्राहकों के लिए विशिष्ट कोड निष्पादित करना चाहता था, लेकिन निष्पादन / निष्कासन से भी बचना चाहता था। मैंने शुरू में प्रत्येक उपयोगकर्ता के लिए एक डेटाबेस में कोड संग्रहीत करने और ऊपर करने के लिए देखा।

मैंने एक 'customer_filters' फोल्डर के भीतर फाइल सिस्टम पर फाइल बनाना और 'imp' मॉड्यूल का उपयोग करना समाप्त कर दिया है, अगर कोई फ़िल्टर उस ग्राहक के लिए लागू नहीं होता है, तो यह सिर्फ चालू रहता है

import imp


def get_customer_module(customerName='default', name='filter'):
    lm = None
    try:
        module_name = customerName+"_"+name;
        m = imp.find_module(module_name, ['customer_filters'])
        lm = imp.load_module(module_name, m[0], m[1], m[2])
    except:
        ''
        #ignore, if no module is found, 
    return lm

m = get_customer_module(customerName, "filter")
if m is not None:
    m.apply_address_filter(myobj)

इसलिए customerName = "jj" ग्राहक_फिल्टर \ jj_filter.py फ़ाइल से apply_address_filter निष्पादित करेगा


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