पायथन का निष्कासन () क्या करता है?


305

जिस किताब में मैं पायथन पर पढ़ रहा हूं, वह कोड का उपयोग करता रहता है eval(input('blah'))

मैं प्रलेखन पढ़ता हूं, और मैं इसे समझता हूं, लेकिन मैं अभी भी यह नहीं देखता कि यह input()फ़ंक्शन कैसे बदलता है ।

यह क्या करता है? क्या कोई समझा सकता है?


4
एवल फ़ंक्शन स्ट्रिंग कोड (तर्क) को निष्पादित करने और व्याख्या करने की कोशिश करता है जो इसे पायथन कोड के रूप में पारित करता है। x = 1 प्रिंट (eval ('x + 1')) उपरोक्त कोड का आउटपुट 2 होगा। इस तरह के दृष्टिकोण का नुकसान यह है कि, उपयोगकर्ता को कोड लिखने की स्वतंत्रता प्राप्त होती है, जिसका परिणाम कहर बन सकता है। अन्यथा आप उपयोगकर्ताओं को प्रतिबंधित कर सकते हैं eval फ़ंक्शन में वैश्विक और स्थानीय पैरामीटर पास करके कई चर और विधियों तक पहुंचना।
ATIF IBAD KHAN

जवाबों:


276

निष्कासन कार्य एक पायथन प्रोग्राम को अपने भीतर पायथन कोड चलाने की सुविधा देता है।

eval उदाहरण (इंटरेक्टिव शेल):

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

25
हाहा, यह एक तुच्छ उदाहरण था, लेकिन आप उपयोगकर्ता को एक अनियंत्रित कमांड में टाइप कर सकते हैं और अजगर को इसे निष्पादित कर सकते हैं। तो आप उपयोगकर्ता प्रकार को कमांड स्ट्रिंग में रख सकते हैं और फिर अजगर को कोड के रूप में चला सकते हैं। इसलिए उदाहरण के लिए: eval ("__ import __ ('os')। निकालें ('फ़ाइल')")।
BYS2

60
यह तब तक बेकार लगेगा जब तक आप इसके लिए एक आवश्यकता नहीं पाते। इसका उपयोग codepad.org जैसी साइटों पर किया जाता है ताकि आप एक परीक्षण वातावरण में स्क्रिप्ट निष्पादित कर सकें। eval()अत्यधिक-गतिशील कोड को निष्पादित करने के लिए भी इस्तेमाल किया जा सकता है, लेकिन आपको इसका उपयोग करने से पहले सुरक्षा और प्रदर्शन जोखिमों से खुद को पूरी तरह से अवगत कराना चाहिए।
जॉर्ज कमिंस

6
@GeorgeCummins, codepad.org उपयोग नहीं करता है eval, और न ही यह इसके साथ क्या कर सकता है eval
माइक ग्राहम

16
@GeorgeCummins: codepag.org सब कुछ सैंडबॉक्स में चलाता है: दुर्भावनापूर्ण कोड को कुछ भी बुरा करने से रोकने के लिए वर्चुअल मशीन में ptrace की जाँच के साथ एक चिरोट जेल। एक साधारण से अधिक जटिल जटिल है। इसके अलावा, पायथन विशिष्ट है। कोडपैड भाषाओं के एक समूह का समर्थन करता है।
फॉगबर्ड

4
@GeorgeCummins, कोडपैड सुरक्षित रूप से मनमाना कार्यक्रम चलाने के लिए एक बहुत ही जटिल प्रणाली चलाता है। eval, असुरक्षित होने के अलावा, कोडपैड जैसे पूरे कार्यक्रम नहीं चला सकते क्योंकि यह केवल एक अभिव्यक्ति का मूल्यांकन कर सकता है।
माइक ग्राहम

165

eval()कोड के रूप में एक स्ट्रिंग की व्याख्या करता है। इसका उपयोग करने के बारे में आपको इतने लोगों ने चेतावनी दी है, इसका कारण यह है कि एक उपयोगकर्ता इसे कंप्यूटर पर कोड चलाने के लिए एक विकल्प के रूप में उपयोग कर सकता है। यदि आपके पास है eval(input())और osआयात किया गया है, तो एक व्यक्ति टाइप कर सकता है, input() os.system('rm -R *')जो आपकी सभी फाइलों को आपके होम डायरेक्टरी में हटा देगा। (मान लें कि आपके पास एक यूनिक्स प्रणाली है)। उपयोग करना eval()एक सुरक्षा छेद है। यदि आपको स्ट्रिंग्स को अन्य प्रारूपों में बदलने की आवश्यकता है, तो उन चीजों का उपयोग करने का प्रयास करें जो ऐसा करते हैं, जैसे int()


14
आप का उपयोग मतलब evalके साथ input()एक सुरक्षा छेद है। input()एक स्पष्ट विवरण के अंदर मत डालो और तुम ठीक हो जाओगे।
रोहमर

19
@ रोमर, असुरक्षित डेटा हर जगह से आ सकते हैं: वेब अनुरोध, फार्म इनपुट फ़ील्ड, फ़ाइल रीड, ... केवल कंसोल इनपुट से नहीं। यहां तक ​​कि अगर आप स्वयं फाइलें लिखते हैं, तो भी इसमें इनपुट हो सकता है जो मूल रूप से एक अविश्वसनीय स्रोत से आया है। तो evalकई मामलों में एक सुरक्षा मुद्दा है।
सैंडरडॉ

3
चूंकि inputआमतौर पर कंसोल से इसका डेटा उपयोगकर्ता लेता है, इसलिए उपयोगकर्ता प्रोग्राम से बाहर निकल सकता है और rm -R *वैसे भी टाइप कर सकता है ...
cz

63

यहाँ बहुत सारे अच्छे उत्तर हैं, लेकिन eval()इसके globalsऔर localsकवारों के संदर्भ में उपयोग का कोई भी वर्णन नहीं करता है , अर्थात eval(expression, globals=None, locals=None)( eval यहाँ के लिए डॉक्स देखें )।

इनका उपयोग फ़ंक्शन के माध्यम से उपलब्ध कार्यों को सीमित करने के लिए किया जा सकता है eval। उदाहरण के लिए यदि आप एक ताजा अजगर इंटरप्रेटर को लोड करते हैं locals()और globals()वह समान होगा और कुछ इस तरह दिखेगा:

>>>globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
 '__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
 '__package__': None, '__name__': '__main__'}

builtinsमॉड्यूल के भीतर निश्चित रूप से कार्य हैं जो एक सिस्टम को महत्वपूर्ण नुकसान पहुंचा सकते हैं। लेकिन कुछ भी और जो कुछ भी हम उपलब्ध नहीं करना चाहते हैं, उसे रोकना संभव है। एक उदाहरण लेते हैं। कहें कि हम सिस्टम पर उपलब्ध कोर के एक डोमेन का प्रतिनिधित्व करने के लिए एक सूची का निर्माण करना चाहते हैं। मेरे लिए मेरे पास 8 कोर हैं इसलिए मुझे एक सूची चाहिए [1, 8]

>>>from os import cpu_count
>>>eval('[1, cpu_count()]')
[1, 8]

इसी तरह सभी __builtins__उपलब्ध है।

>>>eval('abs(-1)')
1

ठीक है। इसलिए, हम एक ऐसा कार्य देखते हैं जिसे हम उजागर करना चाहते हैं और एक का उदाहरण (कई का और अधिक जटिल हो सकता है) विधि जिसे हम उजागर नहीं करना चाहते हैं। तो चलो सब कुछ ब्लॉक।

>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable

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

>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable

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

एनबी

इनके बारे में कुछ और अच्छा kwargsहै कि आप अपने कोड के लिए शॉर्टहैंड का उपयोग करना शुरू कर सकते हैं। मान लें कि आप कुछ आयातित पाठ को निष्पादित करने के लिए पाइपलाइन के हिस्से के रूप में eval का उपयोग करते हैं। पाठ को सटीक कोड की आवश्यकता नहीं है, यह कुछ टेम्प्लेट फ़ाइल प्रारूप का अनुसरण कर सकता है, और फिर भी कुछ भी निष्पादित कर सकता है जो आप चाहते हैं। उदाहरण के लिए:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]

29

पायथन में 2.x input(...)के बराबर है eval(raw_input(...)), पायथन में 3.x raw_inputका नाम बदल दिया गया था input, जिस पर मुझे संदेह है कि आपके भ्रम की स्थिति है (आप शायद inputपायथन 2.x में प्रलेखन देख रहे थे )। इसके अतिरिक्त, eval(input(...))पायथन 3.x में ठीक काम करेगा, लेकिन TypeErrorपायथन 2 में एक जुट करेगा ।

इस मामले में एक अभिव्यक्ति से व्याख्या evalकी गई स्ट्रिंग की inputव्याख्या करने और व्याख्या करने के लिए उपयोग किया जाता है । आमतौर पर यह बुरा अभ्यास माना जाता है।


या यह एक पायथन 3.x पुस्तक है, inputजिसका अर्थ है कि raw_input2.x में क्या किया।
दान ०४

1
हाँ, जो मुझे मेरे प्रारंभिक उत्तर लिखने के बाद हुआ, और यह स्पष्ट रूप से मामला है।
ज़ेके

6

शायद एक पंक्ति को पढ़ने और उसकी व्याख्या करने का एक भ्रामक उदाहरण।

प्रयत्न eval(input()) और टाइप करें "1+1"- यह प्रिंट होना चाहिए 2। मूल्यांकन भावों का मूल्यांकन करता है।


मुझे इसे उद्धरणों के बीच क्यों लिखना चाहिए? इनपुट एक स्ट्रिंग प्राप्त कर रहा है, और इसे कोड से निष्पादित करने के लिए, इसे निष्कासित करने के लिए पारित कर रहा है, इसलिए मुझे ठीक होना चाहिए अगर मैं बस 1 + 1 टाइप करता हूं ...,?
जेसी रोक्मोंडे

बात यह है कि आप P2.x और 3.x को मिला रहे हैं। पायथन 2 में आपका कोड काम करता है, लेकिन दो बार इसे निकालने का कोई मतलब नहीं है। अजगर 3 में यह नहीं है, और एक स्ट्रिंग लौटाता है।
बजे जेसी रोक्मोंडे

6

eval()पायथन अभिव्यक्ति के रूप में पारित स्ट्रिंग का मूल्यांकन करता है और परिणाम देता है। उदाहरण के लिए, eval("1 + 1")अभिव्यक्ति की व्याख्या और निष्पादन करता है"1 + 1" और परिणाम (2) देता है।

आपके द्वारा भ्रमित किए जाने का एक कारण यह हो सकता है कि आपके द्वारा उद्धृत कोड में अप्रत्यक्ष स्तर शामिल है। आंतरिक फ़ंक्शन कॉल (इनपुट) पहले निष्पादित हो जाती है, इसलिए उपयोगकर्ता "ब्लाह" शीघ्र देखता है। आइए कल्पना करें कि वे "1 + 1" के साथ प्रतिक्रिया करते हैं (उद्धरण आपके स्पष्टता के लिए जोड़ा जाता है, अपने प्रोग्राम को चलाते समय उन्हें टाइप न करें), इनपुट फ़ंक्शन उस स्ट्रिंग को लौटाता है, जिसे बाद में बाहरी फ़ंक्शन (eval) में भेजा जाता है जो स्ट्रिंग की व्याख्या करता है और परिणाम (2) देता है।

Eval बारे में अधिक पढ़ें यहाँ


6

eval(), जैसा कि नाम से पता चलता है, पारित तर्क का मूल्यांकन करता है।

raw_input()अब input()अजगर 3.x संस्करणों में है। तो सबसे अधिक पाया जाने वाला उदाहरण eval()इसके उपयोग के लिए है जो कार्यक्षमता प्रदान करता है जो कि input()अजगर के 2.x संस्करण में प्रदान किया गया है। raw_input ने उपयोगकर्ता द्वारा दर्ज किए गए डेटा को एक स्ट्रिंग के रूप में वापस किया, जबकि इनपुट ने दर्ज किए गए डेटा के मूल्य का मूल्यांकन किया और उसे वापस कर दिया।

eval(input("bla bla"))इस प्रकार input(), उपयोगकर्ता द्वारा दर्ज किए गए डेटा का मूल्यांकन करने के लिए, 2.x की कार्यक्षमता को दोहराता है ।

संक्षेप में: इसके eval()लिए पारित तर्कों का मूल्यांकन करता है और इसलिए eval('1 + 1')2 लौटाता है ।


6

उनमें से एक उपयोगी अनुप्रयोग eval()स्ट्रिंग से अजगर के भावों का मूल्यांकन करना है। उदाहरण के लिए फ़ाइल स्ट्रिंग से शब्दकोश का प्रतिनिधित्व:

running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()

इसे एक चर के रूप में पढ़ें और इसे संपादित करें:

fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction

आउटपुट:

{'Greeting': 'Hello world'}

7
यह उस सवाल का जवाब कैसे देता है जो पूछता है कि क्या evalकरता है?
jkd

4

मुझे इस प्रश्न का उत्तर देने में देर हो रही है लेकिन, कोई भी इस प्रश्न का स्पष्ट उत्तर नहीं देता है।

यदि कोई उपयोगकर्ता संख्यात्मक मान दर्ज करता है, input()तो एक स्ट्रिंग लौटाएगा।

>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'

तो, eval()लौटे मूल्य (या अभिव्यक्ति) का मूल्यांकन करेंगे जो एक स्ट्रिंग और रिटर्न पूर्णांक / फ्लोट है।

>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>> 
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14

यह एक बुरा अभ्यास है। int()या इस मामले के float()बजाय इस्तेमाल किया जाना चाहिए eval()

>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14

3

एक अन्य विकल्प यदि आप मूल्यांकन स्ट्रिंग को सरल शाब्दिकता तक सीमित करना चाहते हैं, तो इसका उपयोग करना है ast.literal_eval()। कुछ उदाहरण:

import ast

# print(ast.literal_eval(''))          # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a'))         # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
# print(ast.literal_eval('1+1'))       # 2: but only works due to a quirk in parser
# print(ast.literal_eval('1*1'))       # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}"))     # {'a':1}

से डॉक्स :

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

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

मेलिंग सूची से यह इतना सीमित क्यों है :

शाब्दिक के साथ संचालक अभिव्यक्ति की अनुमति संभव है, लेकिन वर्तमान कार्यान्वयन की तुलना में बहुत अधिक जटिल है। एक सरल कार्यान्वयन सुरक्षित नहीं है: आप बिना किसी प्रयास के मूल रूप से अनबाउंड सीपीयू और मेमोरी उपयोग को प्रेरित कर सकते हैं ("9 ** 9 ** 9" या "[कोई नहीं] * 9 ** 9")।

उपयोगिता के लिए, यह फ़ंक्शन शाब्दिक मूल्यों और कंटेनरों को "रीड बैक" करने के लिए उपयोगी है जैसा कि repr () द्वारा कड़ा किया गया है। यह उदाहरण के लिए एक प्रारूप में क्रमांकन के लिए उपयोग किया जा सकता है जो कि JSON की तुलना में अधिक शक्तिशाली है।


1
ast.literal_evalआपके '1+1'उदाहरण के विपरीत, ऑपरेटरों का समर्थन नहीं करता है । फिर भी यह सूची, संख्या, तार आदि का समर्थन करता है, और इसलिए यह सामान्य evalउपयोग के मामलों के लिए एक अच्छा विकल्प है ।
बेंजामिन

@benjimin ओह आप सही कह रहे हैं - यह सिर्फ एक विचित्रता है कि यह 1 + 1 स्वीकार करता है! stackoverflow.com/questions/40584417/…
ब्रायन बर्न्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.