Python里eval與exec區別 動態代碼執行eval和exec的安全風險

eval()用于計算表達式并返回結果,exec()用于執行語句塊且不返回值。1.eval()處理單個表達式并返回值,如數學運算或字典解析;exec()執行多行代碼或語句塊,如賦值、函數定義等。2.eval()會返回表達式的結果,而exec()僅執行操作無返回值。3.兩者均存在安全風險,若執行不可信輸入可能導致系統破壞或數據泄露,應避免處理用戶輸入,或限制命名空間及使用ast.literal_eval()替代。4.eval()適用于計算表達式,exec()適合動態創建函數或執行腳本。

python 中,eval() 和 exec() 都是用來動態執行字符串形式的代碼,但它們適用的場景和功能有明顯區別。簡單來說,eval() 用于計算表達式并返回結果,而 exec() 用于執行語句塊,不返回值。如果你只是想運行一段動態生成的代碼,用 exec() 更合適;如果只是想求一個表達式的值,比如數學運算或變量替換,就用 eval()。

下面從幾個角度講清楚兩者的差異和潛在風險。


1. 基本功能差異:表達式 vs 語句

  • eval() 只能處理表達式(expression),也就是說它只能執行會返回一個值的代碼。例如:

    result = eval("2 + 3 * 5") print(result)  # 輸出 17
  • exec() 能處理完整的語句塊(statements),包括賦值、函數定義、循環等。例如:

    立即學習Python免費學習筆記(深入)”;

    code = """ a = 10 b = 20 print(a + b) """ exec(code)  # 輸出 30

所以如果你要運行多行代碼或者修改變量狀態,只能用 exec()。


2. 返回值的區別:有沒有結果

  • eval() 會返回表達式的結果。例如:

    value = eval("{'name': 'Tom', 'age': 25}") print(type(value))  # <class 'dict'>
  • exec() 不返回值(返回的是 None),它的作用是“做事情”,而不是“算結果”。比如你可以用它來定義函數:

    exec("def say_hello(): print('Hello!')")  say_hello()  # 輸出 Hello!

3. 安全風險:不要輕易執行不可信輸入

這兩個函數最大的問題就是——它們可以執行任意代碼。如果用戶輸入的內容被當作參數傳給 eval() 或 exec(),那就可能帶來嚴重的安全隱患。

常見風險舉例:

  • 刪除文件、修改系統設置等破壞性操作:

    # 想象用戶輸入了這樣的字符串 user_input = "__import__('os').system('rm -rf /')"  # 如果你用了 eval 或 exec 執行這個字符串……后果嚴重
  • 獲取敏感信息、泄露數據:

    # 用戶構造輸入讀取密碼變量 user_input = "password"

如何降低風險?

  • 盡量避免使用 eval() 和 exec() 處理用戶輸入。

  • 如果一定要用,限制命名空間,禁用內置模塊:

    safe_globals = {"__builtins__": None}  # 禁用所有內置函數 exec("print('hello')", safe_globals)   # 會報錯,無法執行
  • 使用更安全的替代方案,比如 ast.literal_eval() 來解析字符串中的字面量(如列表、字典):

    import ast  data = ast.literal_eval("{'name': 'Tom', 'age': 25}") print(data)  # 安全地轉為 dict

4. 什么時候該用哪個?常見使用場景

場景 推薦使用 說明
計算數學表達式 eval() 比如計算器程序解析輸入
解析字符串成結構化數據 ast.literal_eval() 比如解析 json 字符串
動態創建函數或類 exec() 運行時根據配置生成邏輯
執行用戶自定義腳本 exec() 但要注意權限控制

基本上就這些。eval() 和 exec() 都很強大,但也容易出問題。用的時候要清楚自己在干什么,尤其是面對外部輸入時,千萬不能掉以輕心。

以上就是Python里eval與exec

? 版權聲明
THE END
喜歡就支持一下吧
點贊5 分享