Agar adil, tidak seperti pertanyaan lain, ini bukan duplikat. Dan yang lain telah memposting pertanyaan yang jauh lebih mendasar dari ini.
DNS
8
Jawaban yang benar, tentu saja, hampir selalu "tidak!".
bobince
23
@ S. Lott: Belum membaca FAQ baru-baru ini? "Juga baik-baik saja untuk bertanya dan menjawab pertanyaan pemrograman Anda sendiri, tetapi berpura-pura Anda berada di Jeopardy: frase itu dalam bentuk pertanyaan". Ini bukan pertanyaan yang buruk. +1
Devin Jeanpierre
49
@ S.Lott: Tidak. Anda tidak perlu melakukannya. Jika pertanyaannya belum ada di situs, maka itu adalah permainan yang adil (menurut FAQ, sebagaimana telah ditunjukkan). Jawab saja setiap pertanyaan seolah-olah OP membutuhkan bantuan. Mereka mungkin tidak, tetapi pria berikutnya yang membaca pertanyaan mereka mungkin akan melakukannya. Hanya 2 sen saya.
Bill the Lizard
1
Untuk semua yang Anda katakan tidak melakukannya: Saya punya kasus di mana saya benar-benar perlu. Ini melibatkan pemrosesan terdistribusi.
>>> 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.
tapi bagaimana dengan ruang lingkup kode yang dieksekusi oleh 'exec'? apakah itu bersarang?
jondinham
21
Kasus umum di mana seseorang ingin menggunakan 'exec' adalah sesuatu seperti if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42dll, 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) = 42artinya hal yang sama.
ShreevatsaR
5
Bagaimana exec lebih lambat dari interpreter python?
Cris Stringfellow
6
@ ShreevatsaR bukan maksud Anda setattr(x, s, 42)? Saya mencoba getattr(x, 2) = 42dan gagal dengancan't assign to function call: <string>, line 1
Tanner Semerad
6
@ Tanner: Hmm. Ya memang setattr(x, s, 42)sintaks yang tepat. Terkejut butuh waktu lama untuk kesalahan itu ditangkap. Pokoknya, intinya adalah itu getattrdan setattrmerupakan alternatif execketika semua yang Anda inginkan adalah untuk mendapatkan anggota yang sewenang-wenang, dicari dengan tali.
ShreevatsaR
68
Dalam contoh string dieksekusi sebagai kode menggunakan fungsi exec.
import sys
importStringIO# 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()
bertukar stdout dan stderr seperti itu membuat saya sangat gugup. ini sepertinya bisa menyebabkan masalah keamanan besar. apakah ada jalan lain?
Narcolapser
1
@Narcolapser, Anda harus menjadi mych lebih peduli dengan menggunakan execsama sekali (kecuali Anda tahu string kode berasal dari sumber tepercaya).
bruno desthuilliers
27
evaldan execmerupakan 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 , evaldan execfungsinya 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 =2def 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'isnot 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'isnot defined
Intinya Anda mendefinisikan namespace di mana kode akan dieksekusi.
Tidak mungkin membuat eval aman: Eval benar-benar berbahaya . Jika Anda mengambil kode dari saya dan mengevaluasi itu, saya dapat memisahkan program Python Anda. Permainan telah berakhir.
Ned Batchelder
3
@ v.oddou Saya merespons pernyataan Alan, "eval dan eksekutif .. dapat digunakan dengan cara yang aman." Ini salah. Jika seseorang berkata, "bash dapat digunakan dengan cara yang aman," itu juga akan salah. Bash berbahaya. Ini adalah bahaya yang perlu, tetapi tetap berbahaya. Mengklaim bahwa eval dapat dibuat aman sama sekali salah.
Ned Batchelder
1
@NedBatchelder ya memang. dan tautan yang Anda tuju adalah materi yang bagus. dengan kekuatan datang tanggung jawab, jadi intinya adalah mewaspadai potensi kekuatan eval. dan jika kita memutuskan kekuatan itu = bahaya.
v.oddou
3
@NedBatchelder Banyak potongan kode yang ditulis dengan Python bisa berbahaya juga, tetapi mengapa Anda menganggap itu evalatau execdimaksudkan 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 exectidak aman tidak lebih berbahaya daripada program yang tidak aman melakukan kerusakan dengan sendirinya karena exectidak memberikan hak baru untuk program tersebut.
Thomas Baruchel
1
@ThomasBaruchel lagi, maksud saya adalah untuk melawan anggapan bahwa eval atau exec dapat dibuat aman. Secara khusus, jawaban ini mengklaim bahwa mengendalikan global dan penduduk setempat akan memungkinkan untuk menggunakannya dengan aman. Itu salah. Setiap kali Anda menggunakan exec dan eval, Anda harus tahu persis kode apa yang sedang dieksekusi. Jika tidak, maka Anda terbuka untuk operasi berbahaya.
Ned Batchelder
21
Ingatlah bahwa dari versi 3 execada fungsi!
jadi selalu gunakan exec(mystring)saja exec mystring.
eval()hanya untuk ekspresi, sementara eval('x+1')berfungsi, eval('x=1')tidak akan berfungsi misalnya. Dalam hal ini, lebih baik digunakan exec, atau bahkan lebih baik: cobalah untuk menemukan solusi yang lebih baik :)
Menggunakan execdan evaldengan Python sangat disukai.
Ada alternatif yang lebih baik
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.
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 execitu tidak berarti Anda harus menggunakan alat itu.
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...
Pertama, execmempersulit 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.
"Tebakan terbaik saya adalah bahwa Anda tidak dapat melukai jika Anda tidak dapat menggunakan garis bawah ganda" - Anda dapat membuat string yang berisi garis bawah ganda, dan kemudian panggil eval string itu.
Stanley Bak
saran yang bagus, kecuali Anda menulis generator kode, atau pelari kerja atau serupa ... yang mungkin dilakukan kebanyakan orang di sini.
Erik Aronesty
Saya harus mengimpor path relatif dari file-config ( 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 reldirstring literal ini, tidak dievaluasi, jadi saya tidak bisa membuka file reldir. Apakah anda punya saran?
Marie. P.
9
Anda menyelesaikan mengeksekusi kode menggunakan exec, seperti dengan sesi IDLE berikut:
Ini tidak berfungsi dengan python normal. Setidaknya tidak dalam python 3.
Thomas Ahle
6
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:
Perlu disebutkan, execsaudara itu ada juga dipanggil execfilejika 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.
Solusi paling logis adalah dengan menggunakan fungsi built-in eval () . Solusi lain adalah menulis string itu ke file python sementara dan menjalankannya.
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 =Nonetry:
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 isnotNone:
m.apply_address_filter(myobj)
jadi customerName = "jj" akan mengeksekusi apply_address_filter dari file customer_filters \ jj_filter.py
Jawaban:
Untuk pernyataan, gunakan
exec(string)
(Python 2/3) atauexec string
(Python 2):Saat Anda membutuhkan nilai ekspresi, gunakan
eval(string)
: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.
sumber
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
dll, yang kemudian mereka tulis sebagaiexec ("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 amangetattr
: menulis sajagetattr(x, s) = 42
artinya hal yang sama.setattr(x, s, 42)
? Saya mencobagetattr(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 itugetattr
dansetattr
merupakan alternatifexec
ketika semua yang Anda inginkan adalah untuk mendapatkan anggota yang sewenang-wenang, dicari dengan tali.Dalam contoh string dieksekusi sebagai kode menggunakan fungsi exec.
sumber
exec
sama sekali (kecuali Anda tahu string kode berasal dari sumber tepercaya).eval
danexec
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
danexec
fungsinya mengambil dua parameter tambahan yang memungkinkan pengguna untuk menentukan fungsi dan variabel global dan lokal apa yang tersedia.Sebagai contoh:
Intinya Anda mendefinisikan namespace di mana kode akan dieksekusi.
sumber
eval
atauexec
dimaksudkan untuk digunakanexec(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 mengandungexec
tidak aman tidak lebih berbahaya daripada program yang tidak aman melakukan kerusakan dengan sendirinya karenaexec
tidak memberikan hak baru untuk program tersebut.Ingatlah bahwa dari versi 3
exec
ada fungsi!jadi selalu gunakan
exec(mystring)
sajaexec mystring
.sumber
eval()
hanya untuk ekspresi, sementaraeval('x+1')
berfungsi,eval('x=1')
tidak akan berfungsi misalnya. Dalam hal ini, lebih baik digunakanexec
, atau bahkan lebih baik: cobalah untuk menemukan solusi yang lebih baik :)sumber
Hindari
exec
daneval
Menggunakan
exec
daneval
dengan Python sangat disukai.Ada alternatif yang lebih baik
Dari jawaban teratas (beri penekanan pada saya):
Dari Alternatif ke Eksekutif / Eval?
Itu tidak idiomatis
Dari http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (penekanan pada saya)
Itu berbahaya
Dari http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (penekanan pada saya)
Sulit dibaca dan dimengerti
Dari http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (penekanan tambang):
sumber
cfg.yaml
):,reldir : ../my/dir/
danreldir = 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 gunakanreldir : os.path.join('..','my','dir')
di file konfigurasi. Tapi ini hanya menghasilkanreldir
string literal ini, tidak dievaluasi, jadi saya tidak bisa membuka filereldir
. Apakah anda punya saran?Anda menyelesaikan mengeksekusi kode menggunakan exec, seperti dengan sesi IDLE berikut:
sumber
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:
sumber
Gunakan eval .
sumber
Perlu disebutkan,
exec
saudara itu ada juga dipanggilexecfile
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())
sumber
Lihat eval :
sumber
Saya mencoba beberapa hal, tetapi satu-satunya hal yang berhasil adalah sebagai berikut:
keluaran:
10
sumber
Solusi paling logis adalah dengan menggunakan fungsi built-in eval () . Solusi lain adalah menulis string itu ke file python sementara dan menjalankannya.
sumber
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
jadi customerName = "jj" akan mengeksekusi apply_address_filter dari file customer_filters \ jj_filter.py
sumber