পাইথনের ইওল () কী করে?


305

আমি পাইথনে যে বইটি পড়ছি, তাতে কোডটি ব্যবহার করা যায় eval(input('blah'))

আমি ডকুমেন্টেশনটি পড়েছি এবং আমি এটি বুঝতে পারি, তবে এটি কীভাবে input()ফাংশনটি পরিবর্তন করে তা আমি এখনও দেখতে পাই না ।

এটার কাজ কি? কেউ কি ব্যাখ্যা করতে পারেন?


4
ইভাল ফাংশনটি পাইথন কোড হিসাবে স্ট্রিং (আর্গুমেন্ট) কে কার্যকর এবং ব্যাখ্যা করার চেষ্টা করুন। x = 1 মুদ্রণ (eval ('x + 1')) উপরের কোডটির আউটপুট 2 হবে such এই জাতীয় পদ্ধতির অসুবিধাটি হ'ল, ব্যবহারকারী লেখার কোডের স্বাধীনতা লাভ করে যার ফলে বিপর্যয় পরিস্থিতি দেখা দিতে পারে h আপনি ব্যবহারকারীকে সীমাবদ্ধ রাখতে পারেন ইওল ফাংশনে গ্লোবাল এবং স্থানীয় প্যারামিটারটি পাস করে অনেকগুলি ভেরিয়েবল এবং পদ্ধতি অ্যাক্সেস করা।
এটিআইফ আইব্যাড খান

উত্তর:


276

ইভাল ফাংশনটি একটি পাইথন প্রোগ্রামকে নিজের মধ্যে পাইথন কোড চালাতে দেয়।

উদাহরণস্বরূপ (ইন্টারেক্টিভ শেল):

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

25
হাহা, এটি একটি তুচ্ছ উদাহরণ, তবে আপনি ব্যবহারকারীকে একটি স্বেচ্ছাসেবক কমান্ড টাইপ করতে এবং অজগরটিকে এটি কার্যকর করতে দিতে পারেন। সুতরাং আপনি একটি কমান্ড স্ট্রিং ব্যবহারকারীর টাইপ করতে পারে এবং তারপরে অজগর কোড হিসাবে এটি চালাতে পারেন। সুতরাং উদাহরণস্বরূপ: eval ("__ আমদানি __ ('ওএস')। অপসারণ ('ফাইল')")।
BYS2

60
আপনি এটির কোনও প্রয়োজনীয়তা না পাওয়া পর্যন্ত এটি অকেজো বলে মনে হবে। এটি আপনাকে কোডের পরিবেশে স্ক্রিপ্টগুলি চালানোর অনুমতি দেওয়ার জন্য কোডেপ্যাড.অর্গ.র মতো সাইটে ব্যবহার করা হয়। eval()উচ্চ-গতিশীল কোডটি কার্যকর করতেও ব্যবহার করা যেতে পারে তবে এটি ব্যবহারের আগে আপনার নিজের সুরক্ষা এবং সম্পাদনের ঝুঁকি সম্পর্কে পুরোপুরি সচেতন হওয়া উচিত make
জর্জ কামিন্স

6
@ জর্জিকুমিনস, কোডপ্যাড.আর.জি ব্যবহার করে না eval, বা এটি যা করতে পারে তা করতে পারে না eval
মাইক গ্রাহাম

16
@ জর্জিকুমিনস: কোডপ্যাগ.আর.জি সমস্ত কিছু স্যান্ডবক্সে চালায়: দূষিত কোডটিকে কোনও খারাপ কাজ করতে বাধা দিতে ভার্চুয়াল মেশিনে পিট্রেস চেক সহ একটি ক্রুট জেল। সাধারণ ইওল এর চেয়ে অনেক জটিল। এছাড়াও, ইভাল পাইথন-নির্দিষ্ট। কোডপ্যাড একগুচ্ছ ভাষার সমর্থন করে।
ফোগলবার্ড

4
@ জর্জিকুমিনস, কোডপ্যাড স্বেচ্ছাসেবী কর্মসূচিগুলি নিরাপদে চালানোর জন্য একটি খুব জটিল সিস্টেম চালায়। eval, অনিরাপদ হওয়া ব্যতীত কোডেপ্যাডের মতো পুরো প্রোগ্রাম চালাতে পারে না কারণ এটি কেবলমাত্র একটি একক অভিব্যক্তিকে মূল্যায়ন করতে পারে।
মাইক গ্রাহাম

165

eval()একটি স্ট্রিংকে কোড হিসাবে ব্যাখ্যা করে। এত লোক আপনাকে এটি ব্যবহার সম্পর্কে সতর্ক করার কারণ হ'ল কোনও ব্যবহারকারী কম্পিউটারে কোড চালনার বিকল্প হিসাবে এটি ব্যবহার করতে পারেন। আপনি যদি আমদানি eval(input())এবং osআমদানি করেন তবে কোনও ব্যক্তি এতে টাইপ করতে পারে input() os.system('rm -R *')যা আপনার হোম ডিরেক্টরিতে আপনার সমস্ত ফাইল মুছবে। (ধরে নিচ্ছি আপনার ইউনিক্স সিস্টেম রয়েছে)। ব্যবহার eval()করা একটি সুরক্ষা গর্ত is আপনার যদি স্ট্রিংগুলিকে অন্য ফর্ম্যাটে রূপান্তর করতে হয় তবে এমন জিনিসগুলি ব্যবহার করার চেষ্টা করুন যা পছন্দ করে int()


14
ব্যবহার করে আপনি মানে evalসঙ্গে input()একটি নিরাপত্তা গর্ত হয়। input()একটি খোলামেলা বিবৃতি ভিতরে রাখবেন না এবং আপনি ভাল থাকবেন।
রোহমার

19
@ রোহমের, অনিরাপদ ডেটা যে কোনও জায়গা থেকে আসতে পারে: ওয়েব অনুরোধ, ফর্ম ইনপুট ক্ষেত্রগুলি, ফাইল রিড, ... কেবল কনসোল ইনপুট থেকে নয়। এমনকি আপনি নিজে ফাইলগুলি লিখলেও, এটিতে এখনও ইনপুট থাকতে পারে যা মূলত অবিশ্বস্ত উত্স থেকে এসেছে। evalঅনেক ক্ষেত্রে সুরক্ষার বিষয়টিও তাই ।
sanderd17

3
যেহেতু inputসাধারণত কনসোল থেকে তার ডেটা নেওয়া হয় ব্যবহারকারী কেবল প্রোগ্রামটি থেকে বেরিয়ে rm -R *যেভাবেই টাইপ করতে পারত ...
সিজেড

62

এখানে প্রচুর ভাল উত্তর দেওয়া হয়েছে, তবে eval()এর globalslocalsকাওয়ার্গগুলির প্রসঙ্গে কেউ এর ব্যবহারের বর্ণনা দেয় না , অর্থাৎ 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আপনি আপনার কোডের জন্য শর্টহ্যান্ড ব্যবহার করতে শুরু করতে পারেন। ধরা যাক আপনি কিছু আমদানি করা পাঠ্য কার্যকর করতে পাইপলাইনের অংশ হিসাবে ইওল ব্যবহার করেন। পাঠ্যের সঠিক কোড থাকা দরকার নেই, এটি কিছু টেমপ্লেট ফাইল ফর্ম্যাট অনুসরণ করতে পারে এবং আপনার পছন্দসই কিছু কার্যকর করতে পারে। উদাহরণ স্বরূপ:

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

29

পাইথন ২.x input(...)এর সমান eval(raw_input(...)), পাইথনের ৩.x এর raw_inputনামকরণ করা হয়েছিল input, যা আমি সন্দেহ করি যা আপনার বিভ্রান্তির দিকে নিয়ে যায় (আপনি সম্ভবত inputপাইথন ২.x এর জন্য নথির দিকে তাকিয়ে ছিলেন )। অতিরিক্ত হিসাবে, eval(input(...))পাইথন 3.x এ সূক্ষ্মভাবে কাজ করবে তবে TypeErrorপাইথন 2 এ একটি উত্থাপন করবে ।

এই ক্ষেত্রে evalস্ট্রিং থেকে প্রত্যাগত নিগৃহীত করতে ব্যবহৃত হয় inputএকটি অভিব্যক্তি মধ্যে এবং বুঝিয়ে দিলেন। সাধারণত এটি খারাপ অভ্যাস হিসাবে বিবেচিত হয়।


অথবা এটি একটি পাইথন ৩.x বই, এর inputঅর্থ কী raw_input২.x.
dan04

1
হ্যাঁ আমি আমার প্রাথমিক উত্তরটি লেখার পরে আমার কাছে ঘটেছিল এবং এটি স্পষ্টতই কেস।
zeekay

6

একটি লাইন পড়ার এবং ব্যাখ্যা করার একটি বিভ্রান্তিকর উদাহরণ হতে পারে।

চেষ্টা করুন eval(input())এবং টাইপ করুন "1+1"- এটি মুদ্রণ করা উচিত 2। ইভাল এক্সপ্রেশন মূল্যায়ন।


আমি কেন এটি উদ্ধৃতিগুলির মধ্যে টাইপ করব? ইনপুটটি একটি স্ট্রিং পাচ্ছে, এবং কোডটি চালাচ্ছে না, এটি ওয়াল এ পাস করছে, তাই আমি যদি ভালভাবে 1 + 1 টাইপ করি ... ¿?
জে সি রোকামন্ডে

জিনিসটি আপনি P2.x এবং 3.x মিশ্রিত করছেন that পাইথন 2 এ আপনার কোডটি কাজ করে, তবে এটি দুটিবার বিকাশ লাভ করে না। পাইথন 3 এ এটি হয় না এবং একটি স্ট্রিং দেয়।
জেসি রোকামন্ডে

6

eval()পাইথন এক্সপ্রেশন হিসাবে পাস করা স্ট্রিংকে মূল্যায়ন করে ফলাফলটি দেয়। উদাহরণ স্বরূপ,eval("1 + 1") ব্যাখ্যা এবং এক্সপ্রেশন এক্সপ্রেশন"1 + 1" এবং ফলাফল প্রদান করে (2)।

আপনি বিভ্রান্ত হওয়ার একটি কারণ হ'ল আপনি যে কোডটি উদ্ধৃত করেছেন তাতে একটি স্তর নির্দেশনা জড়িত। অভ্যন্তরীণ ফাংশন কল (ইনপুট) প্রথমে কার্যকর করা হয় যাতে ব্যবহারকারী "ব্লাহ" প্রম্পটটি দেখেন। আসুন কল্পনা করুন যে তারা "1 + 1" (স্পষ্টতার জন্য উদ্ধৃতি যুক্ত হয়েছে, আপনার প্রোগ্রামটি চালনার সময় এগুলি টাইপ করবেন না) দিয়ে প্রতিক্রিয়া জানায়, ইনপুট ফাংশনটি সেই স্ট্রিংটি ফেরত দেয় যা তারপরে বাইরের ফাংশনে (ইওল) পাস হয় যা স্ট্রিংটির ব্যাখ্যা করে এবং ফলাফল প্রদান (2)।

এখানে eval সম্পর্কে আরও পড়ুন ।


6

eval()নামটি যেমন প্রস্তাবিত হয় তত্ক্ষণিত যুক্তিটি মূল্যায়ন করে।

raw_input()input()পাইথন 3.x সংস্করণে এখন । সুতরাং এর ব্যবহারের জন্য সর্বাধিক সন্ধান পাওয়া উদাহরণ eval()হ'ল input()পাইথনের ২.x সংস্করণে কার্যকারিতা সরবরাহ করার জন্য এটির ব্যবহার । কাঁচা-ইনপুট ব্যবহারকারী-প্রবেশ করা ডেটাটিকে স্ট্রিং হিসাবে ফিরিয়ে দেয়, যখন ইনপুট প্রবেশ করা তথ্যের মূল্য নির্ধারণ করে তা ফেরত দেয়।

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" চেষ্টা করুন)।

দরকারীতার হিসাবে, এই ফাংশনটি রিটার () দ্বারা স্ট্রিংযুক্ত হিসাবে আক্ষরিক মান এবং পাত্রে "রিড রিড" উপযোগী। এটি উদাহরণস্বরূপ জেএসএনের চেয়ে বেশি শক্তিশালী এমন ফর্ম্যাটে সিরিয়ালাইজেশনের জন্য ব্যবহার করা যেতে পারে।


1
ast.literal_evalআপনার '1+1'উদাহরণের বিপরীতে অপারেটরদের সমর্থন করে না । তবুও এটি সমর্থন তালিকা, সংখ্যা, স্ট্রিং ইত্যাদি করে এবং তাই সাধারণ evalব্যবহারের ক্ষেত্রে এটি একটি ভাল বিকল্প ।
বেনজিমিন

@ বেঞ্জিমিন ওহ আপনি ঠিক বলেছেন - এটি এমন এক শিঙ্গা যা এটি 1 + 1 গ্রহণ করে! stackoverflow.com/questions/40584417/…
ব্রায়ান বার্নস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.