Eval() làm gì trong python?

Hàm eval trong python nhận đối số bắt buộc - biểu thức. Cùng với điều này, eval trong python cũng có 2 đối số không bắt buộc, chúng là tùy chọn - toàn cầu và cục bộ

  1. đối số biểu thức

    Đây là đối số bắt buộc trong hàm eval trong python. Biểu thức này phải là một chuỗi hoặc đầu vào dựa trên mã được biên dịch. Vì vậy, đầu vào này ở dạng biểu thức khi được cung cấp cho hàm eval được đánh giá là biểu thức Python. Chúng ta sẽ thảo luận chi tiết về điều này trong phần tiếp theo

  2. Đối số toàn cầu

    Đối số này là tùy chọn. Các giá trị được chấp nhận trong đối số này, là các từ điển cung cấp không gian tên chung cho eval[] trong python. Không gian tên về cơ bản là từ điển cung cấp phạm vi cho các đối tượng trong Python. Các từ điển này ánh xạ tên tới các đối tượng. Vì vậy, ở đây, các toàn cầu này trong tham số của eval trong python là tất cả các tên toàn cầu i. e. tất cả những tên hiện có trong phạm vi toàn cầu hoặc không gian tên của bạn, có nghĩa là chúng có thể truy cập được từ bất kỳ đâu trong mã của bạn. Một lần nữa, chúng ta sẽ lấy ví dụ trong một thời gian

  3. Lập luận của người dân địa phương

    Đến với đối số thứ ba, một lần nữa là tùy chọn - người dân địa phương. Điều này cũng sẽ ở dạng từ điển và sẽ chứa tất cả các tên địa phương tôi. e. các tên được xác định bên trong một chức năng và chỉ có thể được truy cập bên trong chức năng cụ thể đó. Trong hàm eval trong python, rõ ràng là bạn không thể thêm các tên biến cục bộ vào hàm này vì nó đã được viết sẵn, nhưng bạn có thể chuyển một từ điển trong đối số local và hàm eval[] này sẽ coi các tên biến đó là local

Giá trị trả về của eval[] trong Python

eval[] trong python trả về giá trị kết quả từ việc đánh giá biểu thức như được đưa ra trong đầu vào của hàm

Ngoại lệ của eval[] trong Python

Tất cả các lỗi cú pháp được báo cáo là ngoại lệ trong chức năng này

Ví dụ về eval[] trong Python

# basic arithmetic
print[eval["3 ** 2"]]  
x = 2
# mathematical expression with local variable a and global variable x
print[eval["x ** 2 + a", {a = 20}]] 

đầu ra

Đánh giá trong Python là gì?

eval[] trong python thực hiện chính xác như tên gọi của nó, nó đánh giá biểu thức được truyền cho nó làm đầu vào. Bây giờ đầu vào này, như đã thảo luận có thể ở định dạng của một chuỗi hoặc đầu vào được biên dịch mã

Đầu vào dựa trên chuỗi trông như thế này - [5∗9][5 * 9][5∗9] về cơ bản là tích của 5 và 9. Điều này khi được truyền dưới dạng biểu thức chuỗi cho phương thức - eval trong python cho chúng ta 45, là tích của hai số. Để cung cấp đầu vào dựa trên mã được biên dịch cho eval trong python, bạn bắt buộc phải sử dụng hàm compile[] trong python. Bằng cách này, bạn có thể cung cấp các đối tượng mã cho eval[] thay cho các chuỗi mà chúng ta đã xem trước đó

Bạn có thể đánh giá điều gì khi sử dụng eval trong python?

Biểu thức toán học, đầu vào của người dùng để đánh giá hàm nhỏ hoặc gọi hàm

Bây giờ khi bạn nhập một chuỗi làm đầu vào trong hàm, eval[] trong python trước tiên sẽ phân tích cú pháp biểu thức mà bạn đã cung cấp, sau đó biên dịch nó thành mã byte. Sau đó, nó được đánh giá là một biểu thức python và kết quả của nó được trả về. Tuy nhiên, nếu bạn cung cấp nó ở định dạng mã được biên dịch, thì nó chỉ đơn giản là đánh giá mã được biên dịch và sau đó trả về kết quả của việc đánh giá đó

Bây giờ bạn đã biết eval[] trong Python làm gì, hãy xem một số ví dụ để xem nó hoạt động như thế nào và bạn có thể sử dụng nó như thế nào

Làm cách nào để sử dụng eval[] trong Python?

  1. Cách sử dụng cơ bản nhất của eval[], với đầu vào chuỗi là biểu thức

    print[eval["3 ** 2"]]
    print[eval["sum[[1, 2, 3, 4]]"]]
    

    đầu ra

  2. Sử dụng đầu vào mã được biên dịch. Hoạt động của hàm compile[] nằm ngoài phạm vi của bài viết này, hãy tham khảo tài liệu chính thức của nó

    code = compile["3 + 7", "", "eval"]
    print[eval[code]]
    

    đầu ra

    # calculating the volume of a cylinder, r = 3, h = 4
    import math
    volume_code = compile["math.pi * math.pow[3, 2] * 4", "", "eval"]
    print[eval[volume_code]]
    

    đầu ra

  3. Sử dụng đối số toàn cầu

    x = 50  # x is a global variable [it is not inside a function]
    print[eval["x * 3", {"x": x}]]
    print[eval["y + 10", {"y": x}]]  # these dicts map names to objects, hence y [name] is mapped to x [object] 
    

    đầu ra

  4. Sử dụng đối số thứ ba -locals. Ở đây, chúng tôi sẽ chuyển đối số toàn cầu dưới dạng một từ điển trống để hiển thị cách chúng tôi đang sử dụng các biến cục bộ

    print[eval["x * 20", {}, {"x": 30}]]  # x is treated as local variable to eval[] function
    

    đầu ra

Ghi chú. Một điểm quan trọng cần lưu ý là để chuyển đối số local mà không có bất kỳ đối số toàn cầu nào, bạn phải cung cấp rõ ràng toàn cầu dưới dạng lệnh trống

Trên đây là một số ví dụ về cách bạn có thể sử dụng eval[] trong python, tuy nhiên, cũng có một số vấn đề quan trọng cần thảo luận

Các vấn đề về lỗ hổng với Eval

Giả sử bạn đang sử dụng hàm eval[] trong Python để nhận đầu vào của người dùng. Bạn không biết người dùng có thể nhập gì vào hàm vì eval[] trong python có thể thực thi bất cứ thứ gì mà nó nhận làm đầu vào. Người dùng có thể gọi các hàm nguy hiểm trong eval[] hoặc thậm chí hiển thị một số giá trị ẩn nhất định có thể gây ra mối đe dọa cho hệ thống bảo mật. Hãy khai thác nó. Giả sử bạn có một hàm chứa khóa bảo mật hoặc dữ liệu bí mật hoặc thậm chí là mật khẩu dưới dạng một trong các biến của nó. Khi bạn đang lấy thông tin đầu vào của người dùng để đánh giá, người dùng có thể gọi chức năng này chứa dữ liệu bí mật và trích xuất thông tin

Hãy xem này

def let_me_in[]:
	secure_key = 'h3k&d*2@'  # confidential data
	print["Here's your confidential data: ", secure_key]  # printing the confidential data

expression = input["Enter a mathematical expression with variable x"]
print[eval[expression]]

Giả sử người dùng nhập chuỗi " let_me_in[] " khi bạn yêu cầu nhập liệu. Đây là đầu ra

Here's your confidential data: h3k&d*2@

Thật dễ dàng để trích xuất khóa bảo mật, chỉ cần gọi một hàm vào hàm eval[]. Bây giờ chúng ta cần ngăn điều này xảy ra vì đây là mối đe dọa bảo mật lớn

Làm cho Eval an toàn

Để giảm rủi ro của chức năng này, chúng tôi có một cách giải quyết. Như chúng ta đã thấy trước đây, eval[] trong python có hai tham số lấy từ điển biến [toàn cầu và cục bộ] được sử dụng để đánh giá biểu thức được đưa ra trong đầu vào, để eval[] có thể truy cập các biến hoặc hàm này. Vì vậy, để làm cho mã an toàn, chúng tôi sẽ chỉ định rõ ràng các biến mà hàm có thể sử dụng. Nếu một biến được đề cập trong từ điển toàn cầu/cục bộ, thì chỉ khi đó biểu thức chứa biến đó mới có thể được phân tích cú pháp để đánh giá. Tuy nhiên nếu biểu thức không chứa biến sẽ trả về lỗi

Đây là cách chúng tôi sẽ làm điều đó

________số 8

đầu ra

# basic arithmetic
print[eval["3 ** 2"]]  
x = 2
# mathematical expression with local variable a and global variable x
print[eval["x ** 2 + a", {a = 20}]] 

0

Bây giờ, hãy thử dùng hàm let_me_in[] làm đầu vào

# basic arithmetic
print[eval["3 ** 2"]]  
x = 2
# mathematical expression with local variable a and global variable x
print[eval["x ** 2 + a", {a = 20}]] 

1

Bây giờ chúng ta an toàn vì hàm eval[] không thể thực thi hàm let_me_in[] và cung cấp cho chúng ta khóa bảo mật vì biểu thức này không chứa biến có trong safe_dict. Thật không may, bằng cách áp dụng các hạn chế bằng cách sử dụng toàn cầu và cục bộ, tất cả các rủi ro bảo mật liên quan đến chức năng này không được loại bỏ vì người dùng sẽ vẫn có quyền truy cập vào các phần mềm cài sẵn của python. Sau này chúng ta sẽ xem làm thế nào để hạn chế những điều đó

Sử dụng của đánh giá

Hàm này được sử dụng trong một số trường hợp hiếm hoi do các vấn đề về lỗ hổng bảo mật mà chúng tôi đã thảo luận ở trên, tuy nhiên, sau đây là cách sử dụng eval[] trong python

  • Cho phép người dùng nhập tập lệnh của họ để giúp tùy chỉnh hành vi của các hệ thống phức tạp
  • Được sử dụng để đánh giá các biểu thức toán học [như đã thảo luận ở trên] trong nhiều ứng dụng thay cho trình phân tích cú pháp biểu thức

Thêm ví dụ

Chúng ta đã thảo luận về nhiều ví dụ, tuy nhiên, hãy xem một số ví dụ khác mà chúng ta đã đưa ra các loại đầu vào khác nhau

  1. Truyền một câu lệnh ghép như if

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    2

    đầu ra

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    3

    eval[] trong python chỉ chấp nhận các biểu thức và không chấp nhận các câu lệnh ghép như if, for, import, while class hoặc def. Họ sẽ đưa ra một SyntaxError

  2. Cách sử dụng biểu thức không đầy đủ / trình phân tích cú pháp biểu thức không thể hiểu được

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    4

    Cả hai điều kiện này sẽ dẫn đến SyntaxError

  3. Cung cấp tên không tồn tại trong phạm vi toàn cầu hiện tại của chương trình

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    5

    đầu ra

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    6

    Ở đây, tên / biến c đã được chuyển đến eval[] trong lệnh toàn cầu và eval[] hiểu nó là một biến toàn cục. Tuy nhiên do không được khai báo rõ ràng trong chương trình nên python không nhận ra biến c

  4. Vượt qua toàn cầu trống

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    7

    đầu ra

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    8

    Hàm eval[] không có quyền truy cập vào " a " vì tham số toàn cầu được truyền dưới dạng lệnh trống

  5. Đánh giá các biểu thức boolean

    # basic arithmetic
    print[eval["3 ** 2"]]  
    x = 2
    # mathematical expression with local variable a and global variable x
    print[eval["x ** 2 + a", {a = 20}]] 
    
    
    9

    đầu ra

  6. Đánh giá các biểu thức mục đích chung

    print[eval["3 ** 2"]]
    print[eval["sum[[1, 2, 3, 4]]"]]
    
    0

    đầu ra

Ví dụ thực tế để chứng minh việc sử dụng eval[]

Hãy lấy một ví dụ mã ngắn để minh họa cách bạn có thể sử dụng eval trong mã của mình. Giả sử bạn muốn tạo một ứng dụng tính chu vi và diện tích của một hình vuông, và bạn muốn người dùng nhập liệu nó muốn tính diện tích hình vuông hay tính chu vi. Đây là cách bạn có thể làm điều đó bằng cách sử dụng eval[] trong python

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
1

đầu ra

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
2

Làm cho một số phương pháp có sẵn

Nếu bạn muốn sử dụng một số chức năng từ một mô-đun không có sẵn trong eval[], bạn có thể thực hiện theo cách sau. Giả sử bạn muốn sử dụng các hàm sqrt[] và pow[] từ mô-đun toán học

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
3

đầu ra

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
4

Hãy nhớ khi chúng tôi nói rằng toàn cầu dict ánh xạ tên tới các đối tượng? . Vì vậy, bây giờ nếu bạn muốn tính toán các biểu thức bằng cách sử dụng các hàm sqrt[] và pow[] từ mô-đun toán ngoài __buildins__, bạn có thể làm như vậy

Hạn chế sử dụng tích hợp sẵn

Chúng tôi có thể ngăn người dùng truy cập một số chức năng nhất định, tuy nhiên, có một lỗ hổng khác mà người dùng có thể khai thác. Hàm eval[] đi kèm với một hàm tích hợp khác __import__[] có thể cung cấp quyền truy cập vào thư viện tiêu chuẩn của python và cả mô-đun bên thứ ba mà bạn có thể đã cài đặt

Chúng tôi biết rằng để sử dụng mô-đun toán học, chúng tôi cần thêm các chức năng của nó vào lệnh toàn cầu. Nhưng nếu chúng ta không làm thì sao?

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
5

đầu ra

Người dùng có thể dễ dàng truy cập bất kỳ mô-đun nào bằng hàm __import__[]. Bây giờ để ngăn chặn điều này, chúng ta phải ghi đè khóa __builtins__ trong lệnh toàn cục như thế này

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
6

đầu ra

print[eval["3 ** 2"]]
print[eval["sum[[1, 2, 3, 4]]"]]
7

Chúng tôi đã ngăn chặn việc sử dụng tích hợp, tuy nhiên không triệt để và rủi ro khi sử dụng eval[] vẫn còn

Mục đích của phương thức eval[] là gì?

Phương thức eval[] đánh giá hoặc thực thi một đối số . Nếu đối số là một biểu thức, eval[] đánh giá biểu thức. Nếu đối số là một hoặc nhiều câu lệnh JavaScript, eval[] sẽ thực thi các câu lệnh.

Sự khác biệt giữa hàm eval[] và INT[] trong Python là gì?

eval đánh giá bất kỳ mã python nào. int cố gắng chuyển đổi bất kỳ loại nào thành số nguyên [float, bool, string. ]. bạn hiểu rồi.

Tôi có thể sử dụng cái gì thay vì eval[] trong Python?

Tùy thuộc vào mức độ phức tạp của biểu thức của bạn, ast. literal_eval có thể là giải pháp thay thế an toàn hơn. literal_eval[] sẽ chỉ đánh giá các chữ, không phải biểu thức đại số.

Chủ Đề