1. 程式人生 > >python3 中的 eval 函式

python3 中的 eval 函式

 

From:http://blog.csdn.net/zhanh1218/article/details/37562167

Python:eval的妙用和濫用:https://blog.csdn.net/zhanh1218/article/details/37562167
python eval():http://www.cnblogs.com/dadadechengzi/p/6149930.html
Python eval 函式妙用:http://www.cnblogs.com/liu-shuai/p/6098246.html
Python 中 eval 帶來的潛在風險:https://blog.csdn.net/u011721501/article/details/47298723


Python之 eval() 函式危險性淺析:https://www.jb51.net/article/51814.htm

 

 

eval() 函式十分強大,官方文件解釋是:將字串 string 物件 轉化為有效的表示式參與求值運算返回計算結果
語法上:呼叫的是:eval(expression,globals=None, locals=None)返回的是計算結果
so,結合 math 當成一個計算器很好用。
可以把 list、tuple、dict 和 string 相互轉化

其中:
        expression 是一個參與計算的 python 表示式
        globals 是可選的引數,如果設定屬性不為 None 的話,就必須是 dictionary 物件了
        locals 也是一個可選的物件,如果設定屬性不為 None 的話,可以是任何 map 物件了

python 是用名稱空間來記錄變數的軌跡的,名稱空間是一個dictionary,鍵是變數名,值是變數值。

當一行程式碼要使用變數 x 的值時,Python 會到所有可用的名字空間去查詢變數,按照如下順序:

  • 1)區域性名字空間 - 特指當前函式或類的方法。
          如果函式定義了一個區域性變數 x, 或一個引數 x,Python 將使用它,然後停止搜尋。
  • 2)全域性名字空間 - 特指當前的模組。如果模組定義了一個名為 x 的變數,函式或類,Python 將使用它然後停止搜尋。
  • 3)內建名字空間 - 對每個模組都是全域性的。作為最後的嘗試,Python 將假設 x 是內建函式或變數。

python 的全域性名字空間儲存在一個叫 globals() 的 dict 物件 中;區域性名字空間儲存在一個叫 locals() 的 dict 物件中。
我們可以用 print (locals()) 來檢視該函式體內的所有變數名和變數值。

下面簡單演示一下 eval()函式的使用:

#!usr/bin/env python
#encoding:utf-8
 
import math
 
 
def eval_test():
    l='[1,2,3,4,[5,6,7,8,9]]'
    d="{'a':123,'b':456,'c':789}"
    t='([1,3,5],[5,6,7,8,9],[123,456,789])'
    print '--------------------------轉化開始--------------------------------'
    print type(l), type(eval(l))
    print type(d), type(eval(d))
    print type(t), type(eval(t))
 
if __name__=="__main__":
    eval_test()

執行結果為:

--------------------------轉化開始--------------------------------
<type 'str'> <type 'list'>
<type 'str'> <type 'dict'>
<type 'str'> <type 'tuple'>
[Finished in 0.2s]

a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
b = eval(a)
b
Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]

type(b)
Out[4]: list
 
a = "{1: 'a', 2: 'b'}"
b = eval(a)
b
Out[7]: {1: 'a', 2: 'b'}
 
type(b)
Out[8]: dict
 
a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
b = eval(a)
 
b
Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))

eval 函式就是實現list、dict、tuple與 str 之間的轉化
str 函式把 list,dict,tuple 轉為為 字串
# 字串轉換成列表
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
print(type(a))
b = eval(a)
print(b)

# 字串轉換成字典
a = "{1: 'a', 2: 'b'}"
print(type(a))
b = eval(a)
print(type(b))
print(b)

# 字串轉換成元組
a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
print(type(a))
b=eval(a)
print(type(b))
print(b)

上面簡單演示的是eval在字串物件和list、dictinoary、tuple物件之間的轉換作用。

不可謂不強大!

BUT!強大的函式有代價。安全性是其最大的缺點。

想一想這種使用環境:需要使用者輸入一個表示式,並求值。

如果使用者惡意輸入,例如:__import__('os').system('dir')
那麼 eval() 之後,你會發現,當前目錄檔案都會展現在使用者前面。

eval(__import__('os').system('dir'))

 

那麼繼續輸入:open('檔名').read()
程式碼都給人看了。獲取完畢,一條刪除命令,檔案消失。哭吧!

 

眾所周知:

eval()的確是一個很便捷的工具,但是便捷使用不當的同時也會造成嚴重的安全問題,不少的文章和部落格都對eval()的安全性進行了相關的分析,在這裡我就不多說了。

怎麼避免安全問題?
1、自行寫檢查函式;
2、使用 ast.literal_eval:自行檢視DOCUMENT:https://docs.python.org/2/library/ast.html
3、更多好文:Restricted "safe" eval(Python recipe):http://code.activestate.com/recipes/496746-restricted-safe-/