2012-02-21 14 views
161

पुस्तक है कि मैं अजगर पर पढ़ रहा हूँ में, यह कोड eval(input('blah'))पायथन का eval() क्या करता है?

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

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

+41

क्या यह एक पायथन 3.x पुस्तक या 2.x एक है? किसी भी तरह से, 'eval' के इस तरह के उदार उपयोग से पता चलता है कि यह एक भयानक किताब है। – delnan

+10

एर्म, बस सोच रहा है ... यह अंगूठे क्यों नीचे आया? शिकायत नहीं, बस मेरे सवालों को सुधारना चाहते हैं .. – Billjk

+5

आपकी पुस्तक भयानक लगता है। आपको एक बेहतर किताब मिलनी चाहिए, शायद http://www.greenteapress.com/thinkpython/html/index.html –

उत्तर

164

eval फ़ंक्शन एक पाइथन प्रोग्राम को अपने भीतर पाइथन कोड चलाता है।

eval उदाहरण (इंटरैक्टिव खोल):

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

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

+44

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

+1

ओह, मुझे यह मिल गया! धन्यवाद – Billjk

24

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

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

+0

या यह एक पायथन 3.x पुस्तक है, जहां 'इनपुट' का मतलब है कि 'raw_input' 2.x में क्या किया गया था। – dan04

+1

हाँ, जब मैंने अपना प्रारंभिक उत्तर लिखा, तो यह मेरे लिए हुआ, और यह स्पष्ट रूप से मामला है। – zeekay

4

शायद एक रेखा पढ़ने और इसे समझने का एक भ्रामक उदाहरण हो सकता है।

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

+0

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

+0

बात यह है कि आप पी 2.एक्स और 3.x मिश्रण कर रहे हैं। पायथन 2 में आपका कोड काम करता है, लेकिन यह दो बार eval करने के लिए समझ में नहीं आता है। पायथन 3 में यह नहीं करता है, और एक स्ट्रिंग देता है। –

5

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

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

eval here eval के बारे में और पढ़ें।

99

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

+11

आपका मतलब है 'इनपुट' के साथ 'eval' का उपयोग करना()' एक सुरक्षा छेद है। एक eval स्टेटमेंट के अंदर 'इनपुट() 'मत डालें और आप ठीक होंगे। – Rohmer

+6

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

3

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 

आउटपुट:

{ 'ग्रीटिंग': 'हैलो वर्ल्ड'}

+3

यह प्रश्न का उत्तर कैसे देता है जो पूछता है कि 'eval' क्या करता है? –

4

eval(), जैसा कि नाम बताता है, उत्तीर्ण तर्क का मूल्यांकन करता है।

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

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

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

4

लॉट के लिए यहाँ अच्छा उत्तरों की, लेकिन कोई भी के संदर्भ में eval के उपयोग का वर्णन इसका globals= और locals= kwargs। इन्हें विधि के माध्यम से उपलब्ध विधियों को सीमित करने के लिए उपयोग किया जा सकता है। उदाहरण के लिए यदि आप एक ताजा अजगर दुभाषिया 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] 
संबंधित मुद्दे