Bagaimana cara menjalankan string yang berisi kode Python di Python?
Bagaimana cara menjalankan string yang berisi kode Python di Python?
Jawaban:
Untuk pernyataan, gunakan exec(string)
(Python 2/3) atau exec string
(Python 2):
>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world
Saat Anda membutuhkan nilai ekspresi, gunakan eval(string)
:
>>> x = eval("2+2")
>>> x
4
Namun, langkah pertama adalah bertanya pada diri sendiri apakah Anda benar-benar perlu. Kode yang dieksekusi umumnya harus menjadi posisi terakhir: Ini lambat, jelek dan berbahaya jika dapat berisi kode yang dimasukkan pengguna. Anda harus selalu melihat alternatif terlebih dahulu, seperti fungsi tingkat tinggi, untuk melihat apakah ini dapat lebih memenuhi kebutuhan Anda.
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
dll, yang kemudian mereka tulis sebagai exec ("x.%s = 42" % s)
. Untuk kasus umum ini (di mana Anda hanya perlu mengakses atribut objek yang disimpan dalam sebuah string), ada fungsi yang jauh lebih cepat, lebih bersih, dan lebih aman getattr
: menulis saja getattr(x, s) = 42
artinya hal yang sama.
setattr(x, s, 42)
? Saya mencoba getattr(x, 2) = 42
dan gagal dengancan't assign to function call: <string>, line 1
setattr(x, s, 42)
sintaks yang tepat. Terkejut butuh waktu lama untuk kesalahan itu ditangkap. Pokoknya, intinya adalah itu getattr
dan setattr
merupakan alternatif exec
ketika semua yang Anda inginkan adalah untuk mendapatkan anggota yang sewenang-wenang, dicari dengan tali.
Dalam contoh string dieksekusi sebagai kode menggunakan fungsi exec.
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()
exec
sama sekali (kecuali Anda tahu string kode berasal dari sumber tepercaya).
eval
dan exec
merupakan solusi yang tepat, dan mereka dapat digunakan dengan cara yang lebih aman .
Sebagaimana dibahas dalam manual referensi Python dan dijelaskan dengan jelas dalam tutorial ini , eval
dan exec
fungsinya mengambil dua parameter tambahan yang memungkinkan pengguna untuk menentukan fungsi dan variabel global dan lokal apa yang tersedia.
Sebagai contoh:
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
Intinya Anda mendefinisikan namespace di mana kode akan dieksekusi.
eval
atau exec
dimaksudkan untuk digunakan exec(input("Type what you want"))
? Ada banyak kasus di mana suatu program dapat menulis prosedur atau fungsi sebagai hasil perhitungan; fungsi yang dihasilkan akan aman dan secepat (setelah dievaluasi) seperti bagian lain dari program yang baik dan ditulis dengan baik. Program yang mengandung exec
tidak aman tidak lebih berbahaya daripada program yang tidak aman melakukan kerusakan dengan sendirinya karena exec
tidak memberikan hak baru untuk program tersebut.
exec
daneval
exec
dan eval
dengan Python sangat disukai.Dari jawaban teratas (beri penekanan pada saya):
Untuk pernyataan, gunakan
exec
.Saat Anda membutuhkan nilai ekspresi, gunakan
eval
.Namun, langkah pertama adalah bertanya pada diri sendiri apakah Anda benar-benar perlu. Kode yang dieksekusi umumnya harus menjadi posisi terakhir : Ini lambat, jelek dan berbahaya jika dapat berisi kode yang dimasukkan pengguna. Anda harus selalu melihat alternatif terlebih dahulu, seperti fungsi tingkat tinggi , untuk melihat apakah ini dapat lebih memenuhi kebutuhan Anda.
Dari Alternatif ke Eksekutif / Eval?
set dan dapatkan nilai variabel dengan nama dalam string
[Sementara
eval
] akan bekerja, umumnya tidak disarankan untuk menggunakan nama variabel yang mengandung arti untuk program itu sendiri.Sebaliknya, lebih baik gunakan dict.
Dari http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (penekanan pada saya)
Python bukan PHP
Jangan mencoba untuk menghindari idiom Python karena beberapa bahasa lain melakukannya secara berbeda. Namespace berada dalam Python karena suatu alasan dan hanya karena memberi Anda alat
exec
itu tidak berarti Anda harus menggunakan alat itu.
Dari http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (penekanan pada saya)
Jadi eval tidak aman, bahkan jika Anda menghapus semua global dan builtin!
Masalah dengan semua upaya ini untuk melindungi eval () adalah bahwa mereka adalah daftar hitam . Mereka secara eksplisit menghapus hal-hal yang bisa berbahaya. Itu adalah pertempuran yang kalah karena jika hanya ada satu item yang tersisa dari daftar, Anda dapat menyerang sistem .
Jadi, bisakah eval dibuat aman? Sulit untuk dikatakan. Pada titik ini, tebakan terbaik saya adalah bahwa Anda tidak dapat membahayakan jika Anda tidak dapat menggunakan garis bawah ganda, jadi mungkin jika Anda mengecualikan string dengan garis bawah ganda, Anda aman. Mungkin...
Dari http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (penekanan tambang):
Pertama,
exec
mempersulit manusia untuk membaca kode Anda . Untuk mengetahui apa yang terjadi, saya tidak hanya harus membaca kode Anda, saya harus membaca kode Anda, mencari tahu string apa yang akan dihasilkan, kemudian membaca kode virtual itu. Jadi, jika Anda bekerja di tim, atau menerbitkan perangkat lunak sumber terbuka, atau meminta bantuan di suatu tempat seperti StackOverflow, Anda mempersulit orang lain untuk membantu Anda. Dan jika ada kemungkinan Anda akan debugging atau memperluas kode ini 6 bulan dari sekarang, Anda membuatnya lebih sulit untuk Anda secara langsung.
cfg.yaml
):, reldir : ../my/dir/
dan reldir = cfg[reldir]
. Namun, karena kode python ini akan berjalan pada Windows dan Linux, saya memerlukan ini untuk menyesuaikan dengan pembagi jalur sistem operasi yang berbeda; salah satu \\
atau /
. Jadi saya gunakan reldir : os.path.join('..','my','dir')
di file konfigurasi. Tapi ini hanya menghasilkan reldir
string literal ini, tidak dievaluasi, jadi saya tidak bisa membuka file reldir
. Apakah anda punya saran?
Anda menyelesaikan mengeksekusi kode menggunakan exec, seperti dengan sesi IDLE berikut:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
Seperti yang disebutkan lainnya, itu "exec" ..
tetapi, jika kode Anda mengandung variabel, Anda dapat menggunakan "global" untuk mengaksesnya, juga untuk mencegah kompiler meningkatkan kesalahan berikut:
NameError: nama 'p_variable' tidak ditentukan
exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
Perlu disebutkan, exec
saudara itu ada juga dipanggil execfile
jika Anda ingin memanggil file python. Itu kadang-kadang bagus jika Anda bekerja dalam paket pihak ketiga yang menyertakan IDE mengerikan dan Anda ingin kode di luar paket mereka.
Contoh:
execfile('/path/to/source.py)'
atau:
exec(open("/path/to/source.py").read())
Saya mencoba beberapa hal, tetapi satu-satunya hal yang berhasil adalah sebagai berikut:
temp_dict = {}
exec("temp_dict['val'] = 10")
print(temp_dict['val'])
keluaran:
10
Ok .. Saya tahu ini bukan jawaban yang tepat, tetapi mungkin catatan untuk orang-orang yang melihat ini seperti saya. Saya ingin mengeksekusi kode khusus untuk pengguna / pelanggan yang berbeda tetapi juga ingin menghindari eksekutif / eval. Saya awalnya mencari menyimpan kode dalam database untuk setiap pengguna dan melakukan hal di atas.
Saya akhirnya membuat file pada sistem file dalam folder 'customer_filters' dan menggunakan modul 'imp', jika tidak ada filter yang diterapkan untuk pelanggan itu, itu hanya dijalankan pada
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)
jadi customerName = "jj" akan mengeksekusi apply_address_filter dari file customer_filters \ jj_filter.py