পাইথনে পাইথন কোডযুক্ত একটি স্ট্রিং আমি কীভাবে কার্যকর করব?


357

পাইথনে পাইথন কোডযুক্ত একটি স্ট্রিং আমি কীভাবে কার্যকর করব?


5
অন্যথাগুলির তুলনায় ন্যায়সঙ্গত হতে, এটি কোনও সদৃশ নয়। এবং অন্যরা এর চেয়ে অনেক বেশি প্রাথমিক প্রশ্ন পোস্ট করেছে।
ডিএনএস

8
সঠিক উত্তর, অবশ্যই, প্রায় সবসময় "না!"।
বোবিনস

23
@S। লট: সম্প্রতি এফএকিউ পড়েনি? "আপনার নিজের প্রোগ্রামিং প্রশ্নটি জিজ্ঞাসা করা এবং উত্তর দেওয়া পুরোপুরি ঠিক আছে, তবে আপনি ঝুঁকির মধ্যে রয়েছেন: এটি একটি প্রশ্নের আকারে উচ্চারণ করুন"। এটি কোনও খারাপ প্রশ্ন নয়। +1
ডেভিন জিনপিয়ের

49
@ এসলট: আপনি করবেন না। আপনার দরকার নেই। যদি প্রশ্নটি ইতিমধ্যে সাইটে না থেকে থাকে, তবে এটি সুষ্ঠু খেলা (এফএকিউ অনুসারে, ইতিমধ্যে দেখানো হয়েছে)। প্রতিটি প্রশ্নের ঠিক উত্তর দিন যেমন ওপির সহায়তার প্রয়োজন। তারা নাও পারে, তবে পরের লোকটি যারা তাদের প্রশ্নটি পড়বে সম্ভবত তা করবে। শুধু আমার 2 সেন্ট।
বিলটি

1
আপনি যা না করার কথা বলছেন সবার কাছে: আমার একটি মামলা রয়েছে যেখানে আমার একেবারে প্রয়োজন। এটি বিতরণ প্রক্রিয়াজাতকরণ জড়িত।
sudo

উত্তর:


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
কিন্তু 'এক্সিকিউটর' দ্বারা সম্পাদিত কোডটির সুযোগ সম্পর্কে কীভাবে? এটা বাসা বেঁধেছে?
jondinham

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
@ নারকোলাপসারটি আপনার ব্যবহার করা সম্পর্কে আরও মনোযোগী হওয়া উচিত exec(যদি না আপনি জানেন যে কোড স্ট্রিং কোনও বিশ্বস্ত উত্স থেকে আসে)।
ব্রুনো ডেসথুইলিয়ার্স

27

evalএবং execসঠিক সমাধান এবং এগুলি নিরাপদ উপায়ে ব্যবহার করা যেতে পারে ।

যেমন আলোচনা হয়েছে পাইথনের রেফারেন্স ম্যানুয়ালটিতে হয়েছে এবং এই টিউটোরিয়ালে পরিষ্কারভাবে ব্যাখ্যা করা হয়েছে , evalএবং execফাংশনগুলি দুটি অতিরিক্ত পরামিতি নেয় যা কোনও ব্যবহারকারীকে কী কী বৈশ্বিক এবং স্থানীয় ফাংশন এবং ভেরিয়েবল উপলব্ধ তা নির্দিষ্ট করতে দেয় to

উদাহরণ স্বরূপ:

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
ওয়াল নিরাপদ করা সম্ভব নয়: ইভাল সত্যই বিপজ্জনক । আপনি যদি আমার কাছ থেকে কোড নিয়ে থাকেন এবং এটিকে ব্যাখ্যা করেন তবে আমি আপনার পাইথন প্রোগ্রামটি সেগফল্ট করতে পারি। খেলা শেষ.
নেড ব্যাচেল্ডার

3
@ v.oddou আমি অ্যালানের এই বক্তব্যের প্রতিক্রিয়া জানিয়েছিলাম, "eval and exec .. নিরাপদ উপায়ে ব্যবহার করা যেতে পারে।" এটা মিথ্যা। যদি কেউ বলে, "বাশ নিরাপদ উপায়ে ব্যবহার করা যেতে পারে", এটিও মিথ্যা হবে। বাশ বিপজ্জনক। এটি একটি প্রয়োজনীয় বিপদ, তবুও বিপজ্জনক। দাবী করা যে এভালকে নিরাপদ করা যায় কেবল ভুল।
নেড ব্যাচেল্ডার

1
@ নেডব্যাচেল্ডার সত্যিই হ্যাঁ। এবং আপনি যে লিঙ্কটি নির্দেশ করেছেন সেটি হ'ল ভাল উপাদান। ক্ষমতার সাথে দায়িত্ব আসে, সুতরাং বিষয়টি সহজভাবে ইওল এর সম্ভাব্য শক্তি সম্পর্কে সচেতন হওয়া। এবং যদি আমরা সেই ক্ষমতা = বিপদ স্থির করি।
v.oddou

3
@ নেড ব্যাচেল্ডার পাইথনে লিখিত অনেকগুলি কোডও বিপজ্জনক হতে পারে তবে আপনি কেন এটি ধরে নিচ্ছেন evalবা execএটি ব্যবহারের উদ্দেশ্যে exec(input("Type what you want"))? এমন অনেকগুলি মামলা রয়েছে যেখানে কোনও প্রোগ্রাম একটি গণনার ফলে কোনও পদ্ধতি বা একটি ফাংশন লিখতে পারে; ফলস্বরূপ ফাংশনগুলি কোনও ভাল এবং লিখিত প্রোগ্রামের অন্য কোনও অংশের মতোই নিরাপদ এবং দ্রুত (একবার মূল্যায়ন করা) হবে। কোনও অনিরাপদ প্রোগ্রাম execথাকা কোনও অনিরাপদ প্রোগ্রামের দ্বারা ক্ষতি সাধন করা তার চেয়ে বেশি বিপজ্জনক নয় কারণ প্রোগ্রামটি execকোনও নতুন সুযোগ দেয় না।
টমাস বারুচেল

1
@ থমাস বারুচেল আবারও, আমার বক্তব্যটি এই ধারণাটি প্রতিরোধ করা যে evভাল বা এক্সিকিউট নিরাপদ করা যায়। বিশেষত, এই উত্তরে দাবি করা হয়েছে যে গ্লোবালগুলি এবং স্থানীয়দের নিয়ন্ত্রণ করা এগুলি নিরাপদে ব্যবহার করা সম্ভব করবে। এটা মিথ্যা। আপনি যখনই এক্সিকিউটিভ এবং বিভক্ত ব্যবহার করেন তখন আপনাকে ঠিক কী কোড কার্যকর করা হচ্ছে তা জানতে হবে। যদি আপনি তা না করেন তবে আপনি বিপজ্জনক অভিযানের জন্য উন্মুক্ত।
নেড ব্যাচেল্ডার

21

মনে রাখবেন যে সংস্করণ 3 থেকে execএকটি ফাংশন!
সুতরাং সর্বদা exec(mystring)পরিবর্তে ব্যবহার করুন exec mystring


11

eval()শুধু এক্সপ্রেশন জন্য, যখন হয় eval('x+1')কাজ, eval('x=1')উদাহরণস্বরূপ কাজ করবে না। সেক্ষেত্রে এটি ব্যবহার করা execআরও ভাল, বা আরও ভাল: আরও ভাল সমাধান খোঁজার চেষ্টা করুন :)


11

এড়ানো execএবংeval

পাইথন ব্যবহার করা execএবং evalএটির উপর অত্যন্ত নীচু ধারণা রয়েছে।

আরও ভাল বিকল্প আছে

উপরের উত্তর থেকে (জোর দেওয়া খনি):

বিবৃতি, ব্যবহারের জন্য exec

যখন আপনার একটি এক্সপ্রেশনটির মান প্রয়োজন হয় তখন ব্যবহার করুন eval

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

থেকে বিকল্প থেকে Exec / Eval?

স্ট্রিংগুলিতে নামের সাথে ভেরিয়েবলের মানগুলি সেট করুন এবং পান

[যখন eval] কাজ করবে, সাধারণত প্রোগ্রামের নিজস্ব অর্থ বহনকারী পরিবর্তনশীল নাম ব্যবহার করার পরামর্শ দেওয়া হয় না।

পরিবর্তে, আরও একটি ডিক ব্যবহার করুন।

এটি মূর্খতা নয়

Http://lucumr.pocoo.org/2011/2/1/exec-in-python/ থেকে (জোর দেওয়া খনি)

পাইথন পিএইচপি নয়

পাইথন রীতিমতো প্রতিরোধ করার চেষ্টা করবেন না কারণ অন্য কিছু ভাষা এটি আলাদাভাবে করে। নেমস্পেসগুলি একটি কারণে পাইথনে রয়েছে এবং কেবল কারণ এটি আপনাকে সরঞ্জাম দেয় execএটির অর্থ এই নয় যে আপনার সেই সরঞ্জামটি ব্যবহার করা উচিত।

এটা বিপজ্জনক

থেকে http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (জোর খনি)

সুতরাং eval নিরাপদ নয়, এমনকি যদি আপনি সমস্ত গ্লোবাল এবং বিল্টিনগুলি সরিয়ে দেন!

এভাল () রক্ষা করার জন্য এই সমস্ত প্রচেষ্টা নিয়ে সমস্যা হ'ল তারা কালো তালিকাভুক্ত । তারা স্পষ্টভাবে এমন জিনিস সরিয়ে দেয় যা বিপজ্জনক হতে পারে। এটি একটি হেরে যাওয়া যুদ্ধ, কারণ যদি তালিকায় কেবল একটি আইটেম বাকি থাকে তবে আপনি সিস্টেমে আক্রমণ করতে পারেন

সুতরাং, কি eval নিরাপদ করা যেতে পারে? বলা কঠিন. এই মুহুর্তে, আমার সর্বোত্তম অনুমান যে আপনি কোনও ডাবল আন্ডারস্কোর ব্যবহার করতে না পারলে আপনি কোনও ক্ষতি করতে পারবেন না, তাই আপনি যদি ডাবল আন্ডারস্কোর সহ কোনও স্ট্রিং বাদ দেন তবে আপনি নিরাপদ। হতে পারে...

এটা পড়া এবং বুঝতে কঠিন

থেকে http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (জোর খনি):

প্রথমত, execআপনার কোডটি পড়া মানুষের পক্ষে আরও কঠিন করে তোলে । কী ঘটছে তা বের করার জন্য, আমাকে কেবল আপনার কোডটি পড়তে হবে না, আমাকে আপনার কোডটি পড়তে হবে, এটি স্ট্রিংটি কী উত্পন্ন করতে চলেছে তা বের করতে হবে, তারপরে সেই ভার্চুয়াল কোডটি পড়তে হবে। সুতরাং, আপনি যদি কোনও দলে কাজ করছেন, বা ওপেন সোর্স সফ্টওয়্যার প্রকাশ করছেন, বা স্ট্যাকওভারফ্লোয়ের মতো কোথাও সাহায্যের জন্য জিজ্ঞাসা করছেন, আপনি অন্য ব্যক্তিকে আপনাকে সহায়তা করা আরও কঠিন করে তুলছেন। এবং যদি এখন থেকে 6 মাস আগে আপনি এই কোডটি ডিবাগিং বা প্রসারিত করার কোনও সম্ভাবনা থাকে তবে আপনি সরাসরি নিজের জন্য আরও শক্ত করে তুলছেন।


"আমার সর্বোত্তম অনুমান যে আপনি কোনও ডাবল আন্ডারস্কোর ব্যবহার করতে না পারলে আপনি কোনও ক্ষতি করতে পারবেন না" - আপনি ডাবল আন্ডারস্কোরযুক্ত একটি স্ট্রিং তৈরি করতে পারেন, এবং তারপরে সেই স্ট্রিংকে ইভাল কল করতে পারেন।
স্ট্যানলি বাক

ভাল পরামর্শ, যদি না আপনি একটি কোড জেনারেটর, বা চাকরী চালক বা অনুরূপ ... লিখছেন যা এখানকার বেশিরভাগ লোক সম্ভবত করছেন।
এরিক অ্যারোনস্টি

আমাকে একটি কনফিগার ফাইল ( cfg.yaml): reldir : ../my/dir/ এবং থেকে একটি আপেক্ষিক পথ আমদানি করতে হবে reldir = cfg[reldir]। তবে, এই অজগর কোডটি উইন্ডোজ এবং লিনাক্স উভয় ক্ষেত্রেই চলবে, বিভিন্ন অপারেটিং সিস্টেমের পাথ ডিভাইডারের সাথে সামঞ্জস্য করার জন্য আমার এটি প্রয়োজন; পারেন \\ বা /। সুতরাং আমি reldir : os.path.join('..','my','dir')কনফিগারেশন ফাইল ব্যবহার । তবে এটি কেবল reldirএই আক্ষরিক স্ট্রিং হওয়ার ফলস্বরূপ , মূল্যায়ন করা হচ্ছে না, তাই আমি কোনও ফাইল খুলতে পারি না reldir। তোমার কি কোন পরামর্শ আছে?
মেরি পি

9

আপনি নিম্নলিখিত আইডিএল সেশনের মতো এক্সিকিউটিভ ব্যবহার করে এক্সিকিউটিং কোডটি সম্পন্ন করেন:

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

4

1
এটি সাধারণ অজগরে কাজ করে না। কমপক্ষে অজগরটি নয় not
থমাস আহলে

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())



1

আমি বেশ কয়েকটি জিনিস চেষ্টা করেছিলাম, তবে কেবলমাত্র কাজটি ছিল নিম্নলিখিত:

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

আউটপুট:

10



0

ঠিক আছে .. আমি জানি এটি ঠিক কোনও উত্তর নয়, তবে সম্ভবত এটির মতো লোকদের জন্য দেখার জন্য একটি নোট। আমি বিভিন্ন ব্যবহারকারীর / গ্রাহকদের জন্য নির্দিষ্ট কোডটি কার্যকর করতে চেয়েছিলাম কিন্তু এক্সিকিউট / এভাল এড়াতেও চেয়েছিলাম। আমি প্রথমে প্রতিটি ব্যবহারকারীর জন্য একটি ডাটাবেসে কোড সংরক্ষণ এবং উপরেরটি করতে চেয়েছিলাম।

আমি একটি 'গ্রাহক_ ফিল্টারস' ফোল্ডারের মধ্যে ফাইল সিস্টেমে ফাইলগুলি তৈরি এবং 'গ্রাহক' মডিউলটি ব্যবহার করে শেষ করেছি, যদি সেই গ্রাহকের জন্য কোনও ফিল্টার প্রয়োগ না করা হয়, তবে এটি চালিয়ে গেছে

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)

সুতরাং গ্রাহক নাম = "জেজে" গ্রাহক_ফিলার্স apply jj_filter.py ফাইল থেকে প্রয়োগ_এড্রেস_ফিল্টার কার্যকর করবে


1
আপনি কীভাবে সুরক্ষা পরিচালনা করলেন? আপনি কীভাবে জানবেন যে গ্রাহকরা এই অধিকারটি অপব্যবহার করবেন না?
জেএসবাচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.