Python tự động gọi phương thức trên đối tượng

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tích hợp sẵn của Python cho phép bạn thực thi mã Python tùy ý từ một chuỗi hoặc đầu vào mã được biên dịch

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể hữu ích khi bạn cần chạy mã Python được tạo động, nhưng nó có thể khá nguy hiểm nếu bạn sử dụng nó một cách bất cẩn. Trong hướng dẫn này, bạn sẽ không chỉ học cách sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 mà còn quan trọng là khi nào bạn có thể sử dụng chức năng này trong mã của mình

Trong hướng dẫn này, bạn sẽ học cách

  • Làm việc với hàm
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1 tích hợp sẵn của Python
  • Sử dụng
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1 để thực thi mã ở dạng chuỗi hoặc đối tượng mã được biên dịch
  • Đánh giá và giảm thiểu rủi ro bảo mật liên quan đến việc sử dụng
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1 trong mã của bạn

Ngoài ra, bạn sẽ viết một số ví dụ về cách sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để giải quyết các vấn đề khác nhau liên quan đến thực thi mã động

Để tận dụng tối đa hướng dẫn này, bạn nên làm quen với các không gian tên và phạm vi của Python và các chuỗi. Bạn cũng nên làm quen với một số hàm có sẵn của Python

Mã mẫu. Nhấp vào đây để tải xuống mã mẫu miễn phí mà bạn sẽ sử dụng để khám phá các trường hợp sử dụng cho hàm exec[]

Làm quen với
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 của Python

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tích hợp sẵn của Python cho phép bạn thực thi bất kỳ đoạn mã Python nào. Với chức năng này, bạn có thể thực thi mã được tạo động. Đó là mã mà bạn đọc, tự động tạo hoặc lấy trong quá trình thực thi chương trình của mình. Thông thường, đó là một chuỗi

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 lấy một đoạn mã và thực thi nó như trình thông dịch Python của bạn sẽ.
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 của Python giống như
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
12 nhưng thậm chí còn mạnh hơn và dễ gặp sự cố bảo mật. Trong khi
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
12 chỉ có thể đánh giá các biểu thức, thì
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể thực thi các chuỗi câu lệnh, cũng như nhập, gọi hàm và định nghĩa, định nghĩa lớp và khởi tạo, v.v. Về cơ bản,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể thực thi toàn bộ chương trình Python đầy đủ tính năng

Chữ ký của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có dạng như sau

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
6

Hàm thực thi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
17, có thể là một chuỗi chứa mã Python hợp lệ hoặc một đối tượng mã được biên dịch

Ghi chú. Python là ngôn ngữ được giải thích thay vì ngôn ngữ được biên dịch. Tuy nhiên, khi bạn chạy một số mã Python, trình thông dịch sẽ dịch mã đó thành mã byte, đây là biểu diễn bên trong của chương trình Python trong triển khai CPython. Bản dịch trung gian này còn được gọi là mã được biên dịch và là thứ mà máy ảo của Python thực thi

Nếu

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
17 là một chuỗi, thì nó được phân tích cú pháp dưới dạng một bộ câu lệnh Python, sau đó được biên dịch nội bộ thành mã byte và cuối cùng được thực thi, trừ khi xảy ra lỗi cú pháp trong bước phân tích cú pháp hoặc biên dịch. Nếu
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
17 giữ một đối tượng mã đã biên dịch, thì nó sẽ được thực thi trực tiếp, làm cho quy trình hiệu quả hơn một chút

Các đối số

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01 cho phép bạn cung cấp các từ điển đại diện cho các không gian tên toàn cục và cục bộ trong đó
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ chạy mã đích

Giá trị trả về của hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
04, có thể vì không phải đoạn mã nào cũng có kết quả cuối cùng, duy nhất và cụ thể. Nó có thể chỉ có một số tác dụng phụ. Hành vi này khác biệt đáng kể so với
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
12, trả về kết quả của biểu thức được đánh giá

Để có cảm nhận ban đầu về cách thức hoạt động của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, bạn có thể tạo một trình thông dịch Python thô sơ với hai dòng mã

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
7

Trong ví dụ này, bạn sử dụng vòng lặp vô hạn

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
07 để bắt chước hành vi của trình thông dịch Python hoặc REPL. Trong vòng lặp, bạn sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
08 để lấy đầu vào của người dùng tại dòng lệnh. Sau đó, bạn sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để xử lý và chạy đầu vào

Ví dụ này giới thiệu những gì được cho là trường hợp sử dụng chính của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. mã thực thi đến với bạn dưới dạng một chuỗi

Ghi chú. Bạn đã học được rằng việc sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể tiềm ẩn rủi ro bảo mật. Bây giờ bạn đã thấy trường hợp sử dụng chính của
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, bạn nghĩ những rủi ro bảo mật đó có thể là gì?

Bạn sẽ thường sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 khi cần chạy mã động ở dạng chuỗi. Ví dụ: bạn có thể viết chương trình tạo chuỗi chứa mã Python hợp lệ. Bạn có thể xây dựng các chuỗi này từ các phần mà bạn có được tại các thời điểm khác nhau trong quá trình thực thi chương trình của mình. Bạn cũng có thể sử dụng đầu vào của người dùng hoặc bất kỳ nguồn đầu vào nào khác để tạo các chuỗi này

Khi bạn đã xây dựng mã mục tiêu dưới dạng chuỗi, thì bạn có thể sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi chúng như cách bạn thực thi bất kỳ mã Python nào

Trong tình huống này, hiếm khi bạn có thể chắc chắn chuỗi của mình sẽ chứa những gì. Đó là một lý do tại sao

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tiềm ẩn những rủi ro bảo mật nghiêm trọng. Điều này đặc biệt đúng nếu bạn đang sử dụng các nguồn đầu vào không đáng tin cậy, chẳng hạn như đầu vào trực tiếp của người dùng, để xây dựng mã của bạn

Trong lập trình, một hàm như

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là một công cụ vô cùng mạnh mẽ vì nó cho phép bạn viết các chương trình tạo và thực thi mã mới một cách linh hoạt. Để tạo mã mới này, chương trình của bạn sẽ chỉ sử dụng thông tin có sẵn trong thời gian chạy. Để chạy mã, các chương trình của bạn sẽ sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Tuy nhiên, với sức mạnh lớn đi kèm với trách nhiệm lớn. Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 ngụ ý những rủi ro bảo mật nghiêm trọng, bạn sẽ sớm tìm hiểu. Vì vậy, bạn nên tránh sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 hầu hết thời gian

Trong các phần sau, bạn sẽ tìm hiểu cách thức hoạt động của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 và cách sử dụng hàm này để thực thi mã ở dạng chuỗi hoặc đối tượng mã được biên dịch

Loại bỏ các quảng cáo

Chạy mã từ đầu vào chuỗi

Cách phổ biến nhất để gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là sử dụng mã đến từ đầu vào dựa trên chuỗi. Để xây dựng đầu vào dựa trên chuỗi này, bạn có thể sử dụng

  • Các dòng mã đơn hoặc đoạn mã một dòng
  • Nhiều dòng mã được phân tách bằng dấu chấm phẩy
  • Nhiều dòng mã được phân tách bằng ký tự dòng mới
  • Nhiều dòng mã trong các chuỗi được trích dẫn ba lần và có thụt lề thích hợp

Chương trình một lớp bao gồm một dòng mã thực hiện nhiều hành động cùng một lúc. Giả sử bạn có một dãy số và bạn muốn tạo một dãy mới chứa tổng bình phương của tất cả các số chẵn trong một dãy đầu vào

Để giải quyết vấn đề này, bạn có thể sử dụng mã một lớp sau

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
3

Trong dòng được đánh dấu, bạn sử dụng biểu thức trình tạo để tính giá trị bình phương của tất cả các số chẵn trong chuỗi giá trị đầu vào. Sau đó, bạn sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
42 để tính tổng bình phương

Để chạy mã này với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, bạn chỉ cần chuyển đổi mã một dòng thành chuỗi một dòng

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84

Trong ví dụ này, bạn thể hiện mã một dòng dưới dạng một chuỗi. Sau đó, bạn đưa chuỗi này vào

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực hiện. Sự khác biệt duy nhất giữa mã ban đầu của bạn và chuỗi là mã sau lưu trữ kết quả tính toán trong một biến để truy cập sau này. Hãy nhớ rằng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trả về
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
04 chứ không phải là kết quả thực thi cụ thể. Tại sao?

Python cho phép bạn viết nhiều câu lệnh trong một dòng mã, sử dụng dấu chấm phẩy để phân tách chúng. Mặc dù thực hành này không được khuyến khích, nhưng sẽ không có gì ngăn cản bạn làm điều gì đó như thế này

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Bạn có thể sử dụng dấu chấm phẩy để phân tách nhiều câu lệnh và tạo chuỗi một dòng dùng làm đối số cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Đây là cách

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
0

Ý tưởng của ví dụ này là bạn có thể kết hợp nhiều câu lệnh Python thành một chuỗi một dòng bằng cách sử dụng dấu chấm phẩy để phân tách chúng. Trong ví dụ, câu lệnh đầu tiên nhận thông tin đầu vào của người dùng, trong khi câu lệnh thứ hai in thông báo lời chào ra màn hình

Bạn cũng có thể tổng hợp nhiều câu lệnh trong một chuỗi một dòng bằng cách sử dụng ký tự xuống dòng,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
48

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
4

Ký tự dòng mới làm cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 hiểu chuỗi một dòng của bạn dưới dạng một tập hợp nhiều câu lệnh Python. Sau đó,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 chạy các câu lệnh tổng hợp liên tiếp, hoạt động giống như một tệp mã nhiều dòng

Cách tiếp cận cuối cùng để xây dựng đầu vào dựa trên chuỗi để cung cấp dữ liệu cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là sử dụng các chuỗi được trích dẫn ba lần. Cách tiếp cận này được cho là linh hoạt hơn và cho phép bạn tạo đầu vào dựa trên chuỗi trông và hoạt động giống như mã Python bình thường

Điều quan trọng cần lưu ý là phương pháp này yêu cầu bạn sử dụng định dạng mã và thụt lề thích hợp. Xem xét ví dụ sau

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
4

Trong ví dụ này, bạn sử dụng chuỗi có ba dấu ngoặc kép để cung cấp đầu vào cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Lưu ý rằng chuỗi này trông giống như bất kỳ đoạn mã Python thông thường nào. Nó sử dụng thụt đầu dòng, kiểu đặt tên và định dạng thích hợp. Hàm
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ hiểu và thực thi chuỗi này như một tệp mã Python thông thường

Bạn nên lưu ý rằng khi bạn chuyển một chuỗi có mã tới

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, hàm sẽ phân tích cú pháp và biên dịch mã đích thành mã byte của Python. Trong mọi trường hợp, chuỗi đầu vào phải chứa mã Python hợp lệ

Nếu

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tìm thấy bất kỳ cú pháp không hợp lệ nào trong các bước phân tích cú pháp và biên dịch, thì mã đầu vào sẽ không chạy

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
3

Trong ví dụ này, mã đích chứa lệnh gọi tới

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
36 lấy một chuỗi làm đối số. Chuỗi này không được kết thúc đúng cách bằng một dấu ngoặc kép đóng, vì vậy,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 đưa ra một
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
38 chỉ ra vấn đề và không chạy mã đầu vào. Lưu ý rằng Python xác định chính xác lỗi ở đầu chuỗi chứ không phải ở cuối, nơi dấu ngoặc kép đóng sẽ xuất hiện

Chạy mã ở dạng chuỗi, giống như bạn đã làm trong ví dụ trên, được cho là cách sử dụng tự nhiên của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Tuy nhiên, nếu bạn cần chạy mã đầu vào nhiều lần, thì việc sử dụng một chuỗi làm đối số sẽ khiến hàm chạy các bước phân tích cú pháp và biên dịch mỗi lần. Hành vi này có thể làm cho mã của bạn không hiệu quả về tốc độ thực thi

Trong tình huống này, cách tiếp cận thuận tiện nhất là biên dịch mã đích trước rồi chạy mã byte kết quả với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 nhiều lần nếu cần. Trong phần sau, bạn sẽ học cách sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 với các đối tượng mã được biên dịch

Loại bỏ các quảng cáo

Thực thi mã biên dịch

Trong thực tế,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể khá chậm khi bạn sử dụng nó để xử lý các chuỗi chứa mã. Nếu bạn cần chạy động một đoạn mã nhất định nhiều lần, thì việc biên dịch nó trước sẽ là phương pháp hiệu quả nhất và được đề xuất. Tại sao?

Để biên dịch một đoạn mã Python, bạn có thể sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13. Hàm tích hợp này lấy một chuỗi làm đối số và chạy quá trình biên dịch mã byte một lần trên đó, tạo đối tượng mã mà sau đó bạn có thể chuyển tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi

Chữ ký của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13 có dạng như sau

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Trong hướng dẫn này, bạn sẽ chỉ sử dụng ba đối số đầu tiên cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13. Đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
17 giữ mã mà bạn cần biên dịch thành mã byte. Đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
18 sẽ giữ tệp mà mã được đọc từ đó. Để đọc từ một đối tượng chuỗi, bạn sẽ phải đặt
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
18 thành giá trị
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
700

Ghi chú. Để tìm hiểu sâu hơn về phần còn lại của các đối số đối với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13, hãy xem tài liệu chính thức của hàm

Cuối cùng,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13 có thể tạo các đối tượng mã mà bạn có thể thực thi bằng cách sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 hoặc
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
12, tùy thuộc vào giá trị của đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
705. Đối số này phải được đặt thành
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
706 hoặc
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
707, tùy thuộc vào chức năng thực thi mục tiêu

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
70

Biên dịch trước mã thường lặp lại với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13 có thể giúp bạn cải thiện một chút hiệu suất mã của mình bằng cách bỏ qua các bước biên dịch mã byte và phân tích cú pháp trên mỗi lệnh gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Chạy mã từ tệp nguồn Python

Bạn cũng có thể sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã mà bạn đã đọc từ tệp
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
711 đáng tin cậy trong hệ thống tệp của mình hoặc ở một nơi khác. Để làm điều này, bạn có thể sử dụng hàm
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
712 tích hợp sẵn để đọc nội dung của tệp dưới dạng một chuỗi, sau đó bạn có thể chuyển hàm này làm đối số cho
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Ví dụ: giả sử bạn có tệp Python có tên

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
714 chứa đoạn mã sau

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
71

Tập lệnh mẫu này in lời chào và thông báo chào mừng ra màn hình. Nó cũng định nghĩa một hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
715 mẫu cho mục đích thử nghiệm. Hàm lấy tên làm đối số và in lời chào tùy chỉnh ra màn hình

Bây giờ hãy quay lại phiên tương tác Python của bạn và chạy đoạn mã sau

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
72

Trong ví dụ này, trước tiên bạn mở tệp

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
711 đích dưới dạng tệp văn bản thông thường bằng cách sử dụng hàm
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
712 tích hợp trong câu lệnh
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
718. Sau đó, bạn gọi
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
719 trên đối tượng tệp để đọc nội dung của tệp vào biến
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
17. Cuộc gọi này tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
719 trả về nội dung của tệp dưới dạng một chuỗi. Bước cuối cùng là gọi
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 với chuỗi này làm đối số

Ví dụ này chạy mã và làm cho hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
715 và các đối tượng sống trong
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
714 có sẵn trong không gian tên hiện tại của bạn. Đó là lý do tại sao bạn có thể sử dụng trực tiếp
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
715. Bí mật đằng sau hành vi này liên quan đến các đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01 mà bạn sẽ tìm hiểu trong phần tiếp theo

Sử dụng kỹ thuật trong ví dụ trên, bạn có thể mở, đọc và thực thi bất kỳ tệp nào chứa mã Python. Kỹ thuật này có thể hoạt động khi bạn không biết trước mình sẽ chạy tệp nguồn nào. Vì vậy, bạn không thể viết

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
728, vì bạn không biết tên của mô-đun khi viết mã

Ghi chú. Trong Python, bạn sẽ tìm thấy những cách an toàn hơn để đạt được kết quả tương tự. Bạn có thể sử dụng hệ thống nhập khẩu, ví dụ. Để tìm hiểu sâu hơn về giải pháp thay thế này, hãy xem Nhập động

Nếu bạn từng chọn sử dụng kỹ thuật này, hãy đảm bảo rằng bạn chỉ thực thi mã từ các tệp nguồn đáng tin cậy. Lý tưởng nhất là các tệp nguồn đáng tin cậy nhất là những tệp mà bạn đã tạo một cách có ý thức để chạy động. Bạn không bao giờ được chạy các tệp mã đến từ các nguồn bên ngoài, bao gồm cả người dùng của bạn mà không kiểm tra mã trước

Loại bỏ các quảng cáo

Sử dụng đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01

Bạn có thể chuyển bối cảnh thực thi tới

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 bằng cách sử dụng các đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01. Các đối số này có thể chấp nhận các đối tượng từ điển sẽ hoạt động như các không gian tên toàn cục và cục bộ mà
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ sử dụng để chạy mã đích

Các đối số này là tùy chọn. Nếu bạn bỏ qua chúng, thì

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ thực thi mã đầu vào trong phạm vi hiện tại và tất cả các tên cũng như đối tượng trong phạm vi này sẽ có sẵn cho
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Tương tự như vậy, tất cả các tên và đối tượng mà bạn xác định trong mã đầu vào sẽ có sẵn trong phạm vi hiện tại sau lệnh gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Xem xét ví dụ sau

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
73

Ví dụ này cho thấy rằng nếu bạn gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 mà không cung cấp các giá trị cụ thể cho các đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, thì hàm sẽ chạy mã đầu vào trong phạm vi hiện tại. Trong trường hợp này, phạm vi hiện tại là phạm vi toàn cầu

Lưu ý rằng sau khi bạn gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, các tên được xác định trong mã đầu vào cũng có sẵn trong phạm vi hiện tại. Đó là lý do tại sao bạn có thể truy cập
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
742 ở dòng mã cuối cùng

Nếu bạn chỉ cung cấp một giá trị cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00, thì giá trị đó phải là một từ điển. Hàm
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ sử dụng từ điển này cho cả tên toàn cục và tên cục bộ. Hành vi này sẽ hạn chế quyền truy cập vào hầu hết các tên trong phạm vi hiện tại

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
74

Trong lần gọi đầu tiên tới

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, bạn sử dụng từ điển làm đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00. Vì từ điển của bạn không cung cấp khóa chứa tên
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
747, lệnh gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 không có quyền truy cập vào tên này và phát sinh ngoại lệ
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
749

Trong lần gọi thứ hai tới

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, bạn cung cấp một từ điển khác cho
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00. Trong trường hợp này, từ điển chứa cả hai biến,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
752 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
747, cho phép hàm hoạt động bình thường. Tuy nhiên, lần này bạn không có quyền truy cập vào
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
742 sau cuộc gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Tại sao?

Nếu bạn gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 bằng một từ điển
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 không chứa khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759 một cách rõ ràng, thì Python sẽ tự động chèn một tham chiếu đến phạm vi hoặc không gian tên tích hợp bên dưới khóa đó. Vì vậy, tất cả các đối tượng tích hợp sẽ có thể truy cập được từ mã mục tiêu của bạn

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
75

Trong ví dụ này, bạn đã cung cấp một từ điển trống cho đối số

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00. Lưu ý rằng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 vẫn có quyền truy cập vào không gian tên tích hợp vì không gian tên này được tự động chèn vào từ điển được cung cấp theo khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759

Nếu bạn cung cấp một giá trị cho đối số

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, thì đó có thể là bất kỳ đối tượng ánh xạ nào. Đối tượng ánh xạ này sẽ giữ không gian tên cục bộ khi
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 đang chạy mã mục tiêu của bạn

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
76

Cuộc gọi đến

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 được nhúng trong một chức năng trong ví dụ này. Do đó, bạn có phạm vi toàn cầu [cấp mô-đun] và phạm vi cục bộ [cấp chức năng]. Đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 cung cấp tên
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
752 từ phạm vi toàn cầu và đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01 cung cấp tên
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
747 từ phạm vi cục bộ

Lưu ý rằng sau khi chạy

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
770, bạn không có quyền truy cập vào
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
742 vì tên này được tạo trong phạm vi cục bộ của
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, không có sẵn từ bên ngoài

Với các đối số

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, bạn có thể điều chỉnh ngữ cảnh trong đó
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 chạy mã của bạn. Những lập luận này khá hữu ích khi nói đến việc giảm thiểu rủi ro bảo mật liên quan đến
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, nhưng bạn vẫn nên đảm bảo rằng bạn chỉ đang chạy mã từ các nguồn đáng tin cậy. Trong phần sau, bạn sẽ tìm hiểu về những rủi ro bảo mật này và cách đối phó với chúng

Khám phá và giảm thiểu rủi ro bảo mật đằng sau
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Như bạn đã học cho đến nay,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là một công cụ mạnh mẽ cho phép bạn thực thi mã tùy ý dưới dạng chuỗi. Bạn nên sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 hết sức cẩn thận và thận trọng vì khả năng chạy bất kỳ đoạn mã nào của nó

Thông thường, mã nguồn cung cấp

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 được tạo động khi chạy. Mã này có thể có nhiều nguồn đầu vào, có thể bao gồm người dùng chương trình của bạn, các chương trình khác, cơ sở dữ liệu, luồng dữ liệu và kết nối mạng, trong số những nguồn khác

Trong trường hợp này, bạn không thể hoàn toàn chắc chắn chuỗi đầu vào sẽ chứa gì. Vì vậy, xác suất đối mặt với nguồn mã đầu vào không đáng tin cậy và độc hại là khá cao

Các vấn đề bảo mật liên quan đến

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là lý do phổ biến nhất khiến nhiều nhà phát triển Python khuyên bạn nên tránh hoàn toàn chức năng này. Tìm kiếm một giải pháp tốt hơn, nhanh hơn, mạnh mẽ hơn và an toàn hơn hầu như luôn luôn có thể

Tuy nhiên, nếu bạn phải sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trong mã của mình, thì cách tiếp cận thường được khuyến nghị là sử dụng nó với từ điển rõ ràng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01

Một vấn đề nghiêm trọng khác với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 là nó phá vỡ một giả định cơ bản trong lập trình. mã mà bạn hiện đang đọc hoặc viết là mã mà bạn sẽ thực thi khi khởi động chương trình của mình. Làm thế nào để
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 phá vỡ giả định này? . Mã mới này có thể khó theo dõi, duy trì hoặc thậm chí kiểm soát

Trong các phần sau, bạn sẽ đi sâu vào một số đề xuất, kỹ thuật và thực hành mà bạn nên áp dụng nếu cần sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trong mã của mình

Loại bỏ các quảng cáo

Tránh đầu vào từ các nguồn không đáng tin cậy

Nếu người dùng của bạn có thể cung cấp cho chương trình của bạn mã Python tùy ý trong thời gian chạy, thì vấn đề có thể phát sinh nếu họ nhập mã vi phạm hoặc vi phạm quy tắc bảo mật của bạn. Để minh họa vấn đề này, hãy quay lại ví dụ về trình thông dịch Python sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi mã

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
77

Bây giờ, giả sử bạn muốn sử dụng kỹ thuật này để triển khai trình thông dịch Python tương tác trên một trong các máy chủ web Linux của bạn. Nếu bạn cho phép người dùng của mình chuyển trực tiếp mã tùy ý vào chương trình của bạn, thì người dùng ác ý có thể cung cấp nội dung như

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
789. Đoạn mã này có thể sẽ xóa tất cả nội dung trên đĩa máy chủ của bạn, vì vậy đừng chạy nó

Để ngăn ngừa rủi ro này, bạn có thể hạn chế quyền truy cập vào hệ thống

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
790 bằng cách tận dụng từ điển
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
78

Hệ thống

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
790 bên trong sử dụng chức năng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
793 tích hợp. Vì vậy, nếu bạn cấm truy cập vào không gian tên tích hợp, thì hệ thống
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
790 sẽ không hoạt động

Mặc dù bạn có thể điều chỉnh từ điển

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 như minh họa trong ví dụ trên, một điều mà bạn không bao giờ được làm là sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã bên ngoài và có khả năng không an toàn trên máy tính của bạn. Ngay cả khi bạn dọn dẹp cẩn thận và xác thực thông tin đầu vào, bạn vẫn có nguy cơ bị tấn công. Vì vậy, tốt nhất bạn nên tránh thực hành này

Hạn chế
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01 để giảm thiểu rủi ro

Bạn có thể cung cấp từ điển tùy chỉnh dưới dạng đối số

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01 nếu bạn muốn tinh chỉnh quyền truy cập vào tên toàn cầu và tên cục bộ khi chạy mã với
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Ví dụ: nếu bạn chuyển các từ điển trống cho cả
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, thì
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ không có quyền truy cập vào các không gian tên toàn cầu và cục bộ hiện tại của bạn

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
79

Nếu bạn gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 với các từ điển trống cho
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, thì bạn cấm truy cập vào tên toàn cầu và tên địa phương. Tinh chỉnh này cho phép bạn hạn chế tên và đối tượng khả dụng khi bạn đang chạy mã với
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Tuy nhiên, kỹ thuật này không đảm bảo sử dụng an toàn

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Tại sao?

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
30

Trong các ví dụ này, bạn sử dụng các từ điển trống cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, nhưng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 vẫn có thể truy cập các chức năng tích hợp sẵn như
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
315,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
316 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
36. Làm thế nào bạn có thể ngăn chặn
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 truy cập vào các tên dựng sẵn?

Quyết định các tên tích hợp được phép

Như bạn đã biết, nếu bạn chuyển một từ điển tùy chỉnh cho

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 mà không có khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759, thì Python sẽ tự động cập nhật từ điển đó với tất cả các tên trong phạm vi tích hợp theo khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759 mới. Để hạn chế hành vi tiềm ẩn này, bạn có thể sử dụng từ điển
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 chứa khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759 với giá trị phù hợp

Ví dụ: nếu bạn muốn cấm hoàn toàn quyền truy cập vào các tên dựng sẵn, thì bạn có thể gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 như trong ví dụ sau

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
31

Trong ví dụ này, bạn đặt

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 thành một từ điển tùy chỉnh có chứa khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759 với một từ điển trống làm giá trị được liên kết của nó. Thực tiễn này ngăn Python chèn tham chiếu đến không gian tên tích hợp vào
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00. Bằng cách này, bạn đảm bảo rằng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sẽ không có quyền truy cập vào tên tích hợp trong khi thực thi mã của bạn

Bạn cũng có thể điều chỉnh khóa

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759 của mình nếu bạn chỉ cần
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để truy cập một số tên tích hợp nhất định

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
32

Trong ví dụ đầu tiên,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 chạy thành công mã đầu vào của bạn vì
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
315 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
36 có trong từ điển được liên kết với khóa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
759. Trong ví dụ thứ hai,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tăng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
749 và không chạy mã đầu vào của bạn vì
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
316 không có trong
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
338 được cung cấp

Các kỹ thuật trong các ví dụ trên cho phép bạn giảm thiểu tác động bảo mật của việc sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Tuy nhiên, những kỹ thuật này không hoàn toàn dễ dàng. Vì vậy, bất cứ khi nào bạn cảm thấy cần sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, hãy thử nghĩ ra một giải pháp khác không sử dụng hàm

Loại bỏ các quảng cáo

Đưa
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 vào hành động

Cho đến thời điểm này, bạn đã học được cách hoạt động của hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tích hợp. Bạn biết rằng bạn có thể sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy đầu vào dựa trên chuỗi hoặc mã được biên dịch. Bạn cũng biết rằng hàm này có thể nhận hai đối số tùy chọn,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, cho phép bạn điều chỉnh không gian tên thực thi cho
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1

Ngoài ra, bạn đã biết rằng việc sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 hàm ý một số vấn đề bảo mật nghiêm trọng, bao gồm việc cho phép người dùng chạy mã Python tùy ý trên máy tính của bạn. Bạn đã nghiên cứu một số phương pháp mã hóa được đề xuất giúp giảm thiểu rủi ro bảo mật liên quan đến
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trong mã của bạn

Trong các phần sau, bạn sẽ viết mã một số ví dụ thực tế giúp bạn phát hiện ra những trường hợp sử dụng mà việc sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 có thể phù hợp

Chạy mã từ các nguồn bên ngoài

Sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi mã ở dạng chuỗi từ người dùng của bạn hoặc bất kỳ nguồn nào khác có lẽ là trường hợp sử dụng nguy hiểm và phổ biến nhất của
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Hàm này là cách nhanh nhất để bạn chấp nhận mã dưới dạng chuỗi và chạy nó như mã Python thông thường trong ngữ cảnh của một chương trình nhất định

Bạn không bao giờ được sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã bên ngoài tùy ý trên máy của mình, vì không có cách nào an toàn để thực hiện việc đó. Nếu bạn định sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, thì hãy sử dụng nó như một cách để cho phép người dùng của bạn chạy mã của riêng họ trên máy của chính họ

Thư viện tiêu chuẩn có một số mô-đun sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi mã do người dùng cung cấp dưới dạng chuỗi. Một ví dụ điển hình là mô-đun
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
355, mà Guido van Rossum đã tự viết ban đầu

Mô-đun

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
355 cung cấp một cách nhanh chóng để tính thời gian cho các đoạn mã Python nhỏ có dạng chuỗi. Xem ví dụ sau từ tài liệu của mô-đun

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
33

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
357 lấy đoạn mã dưới dạng chuỗi, chạy mã và trả về phép đo thời gian thực hiện. Hàm này cũng nhận một số đối số khác. Ví dụ:
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
358 cho phép bạn cung cấp số lần bạn muốn thực thi mã mục tiêu

Tại trung tâm của chức năng này, bạn sẽ tìm thấy lớp

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
359.
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
359 sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã được cung cấp. Nếu bạn kiểm tra mã nguồn của
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
359 trong mô-đun
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
355, thì bạn sẽ thấy rằng trình khởi tạo của lớp,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
364, bao gồm mã sau

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
34

Cuộc gọi đến

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trong dòng được đánh dấu sẽ thực thi mã của người dùng bằng cách sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
366 và
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
367 làm không gian tên toàn cầu và cục bộ của nó

Cách sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 này phù hợp khi bạn đang cung cấp công cụ cho người dùng của mình, những người sẽ phải cung cấp mã mục tiêu của riêng họ. Mã này sẽ chạy trên máy của người dùng, vì vậy họ sẽ chịu trách nhiệm đảm bảo rằng mã đầu vào được chạy an toàn

Một ví dụ khác về việc sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã dưới dạng chuỗi là mô-đun
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370. Mô-đun này kiểm tra chuỗi tài liệu của bạn để tìm kiếm văn bản giống như phiên tương tác Python. Nếu
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 tìm thấy bất kỳ văn bản nào giống như phiên tương tác, thì nó sẽ thực thi văn bản đó dưới dạng mã Python để kiểm tra xem nó có hoạt động như mong đợi không

Ví dụ: giả sử bạn có hàm sau để cộng hai số với nhau

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
35

Trong đoạn mã này,

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
372 định nghĩa một chuỗi tài liệu với một số bài kiểm tra để kiểm tra xem chức năng sẽ hoạt động như thế nào. Lưu ý rằng các bài kiểm tra đại diện cho các lệnh gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
372 trong phiên tương tác giả định sử dụng các loại đối số hợp lệ và không hợp lệ

Sau khi bạn có các bài kiểm tra tương tác này và kết quả đầu ra dự kiến ​​của chúng trong chuỗi tài liệu của mình, thì bạn có thể sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 để chạy chúng và kiểm tra xem chúng có đưa ra kết quả như mong đợi không

Ghi chú. Mô-đun doctest cung cấp một công cụ tuyệt vời và hữu ích mà bạn có thể sử dụng để kiểm tra mã của mình trong khi viết mã

Chuyển đến dòng lệnh của bạn và chạy lệnh sau trong thư mục chứa tệp

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
375 của bạn

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
36

Lệnh này sẽ không đưa ra bất kỳ đầu ra nào nếu tất cả các thử nghiệm hoạt động như mong đợi. Nếu ít nhất một thử nghiệm không thành công, thì bạn sẽ nhận được một ngoại lệ chỉ ra vấn đề. Để xác nhận điều này, bạn có thể thay đổi một trong các đầu ra dự kiến ​​trong chuỗi tài liệu của hàm và chạy lại lệnh trên

Mô-đun

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi bất kỳ mã nhúng chuỗi tài liệu tương tác nào, như bạn có thể xác nhận trong mã nguồn của mô-đun

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
37

Như bạn có thể xác nhận trong đoạn mã này, mã của người dùng chạy trong lệnh gọi

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
13 để biên dịch mã đích. Để chạy mã này,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 sử dụng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
381 làm đối số
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
00 của nó. Lưu ý rằng nhận xét ngay trước lệnh gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 nói đùa rằng đây là nơi mã của người dùng chạy

Một lần nữa, trong trường hợp sử dụng của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 này, trách nhiệm cung cấp các ví dụ mã an toàn thuộc về người dùng. Người bảo trì
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 không chịu trách nhiệm đảm bảo rằng cuộc gọi tới
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 không gây ra bất kỳ thiệt hại nào

Điều quan trọng cần lưu ý là

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 không ngăn chặn các rủi ro bảo mật liên quan đến
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Nói cách khác,
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 sẽ chạy bất kỳ mã Python nào. Ví dụ: ai đó có thể sửa đổi hàm
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
372 của bạn để đưa đoạn mã sau vào chuỗi tài liệu

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
38

Nếu bạn chạy

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370 trên tệp này, thì lệnh
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
392 sẽ chạy thành công. Trong ví dụ này, lệnh nhúng hầu như vô hại. Tuy nhiên, người dùng ác ý có thể sửa đổi chuỗi tài liệu của bạn và nhúng thứ gì đó như
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
393 hoặc bất kỳ lệnh nguy hiểm nào khác

Một lần nữa, bạn luôn phải cẩn thận với

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 và với các công cụ sử dụng chức năng này, chẳng hạn như
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370. Trong trường hợp cụ thể của
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
370, miễn là bạn biết mã kiểm tra được nhúng của mình đến từ đâu, công cụ này sẽ khá an toàn và hữu ích

Loại bỏ các quảng cáo

Sử dụng Python cho tệp cấu hình

Một tình huống khác mà bạn có thể sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để chạy mã là khi bạn có tệp cấu hình sử dụng cú pháp Python hợp lệ. Tệp của bạn có thể xác định một số tham số cấu hình với các giá trị cụ thể. Sau đó, bạn có thể đọc tệp và xử lý nội dung của nó bằng
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để xây dựng một đối tượng từ điển chứa tất cả các tham số cấu hình của bạn và các giá trị của chúng

Ví dụ: giả sử bạn có tệp cấu hình sau cho ứng dụng soạn thảo văn bản mà bạn đang làm việc

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
39

Tệp này có cú pháp Python hợp lệ, vì vậy bạn có thể thực thi nội dung của nó bằng cách sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 như cách bạn thực hiện với tệp
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
711 thông thường

Ghi chú. Bạn sẽ tìm thấy một số cách tốt hơn và an toàn hơn để làm việc với các tệp cấu hình hơn là sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Trong thư viện chuẩn Python, bạn có mô-đun
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
02, cho phép bạn xử lý các tệp cấu hình sử dụng định dạng tệp INI

Hàm bên dưới đọc tệp

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
03 của bạn và xây dựng từ điển cấu hình

>>>

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
0

Hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
04 lấy đường dẫn đến tệp cấu hình. Sau đó, nó đọc tệp đích dưới dạng văn bản và chuyển văn bản đó vào
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 để thực thi. Trong quá trình chạy
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1, hàm đưa các tham số cấu hình vào từ điển
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
01, từ điển này sau đó được trả về mã người gọi

Ghi chú. Kỹ thuật trong phần này có lẽ là trường hợp sử dụng an toàn của

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1. Trong ví dụ này, bạn sẽ có một ứng dụng đang chạy trên hệ thống của mình, cụ thể là trình soạn thảo văn bản

Nếu bạn sửa đổi tệp cấu hình của ứng dụng để bao gồm mã độc, thì bạn sẽ chỉ tự làm hại chính mình, điều mà rất có thể bạn sẽ không làm. Tuy nhiên, vẫn có khả năng bạn vô tình đưa mã nguy hiểm tiềm tàng vào tệp cấu hình của ứng dụng. Vì vậy, kỹ thuật này có thể không an toàn nếu bạn không cẩn thận

Tất nhiên, nếu bạn đang tự mã hóa ứng dụng và bạn phát hành tệp cấu hình chứa mã độc, thì bạn sẽ gây hại cho cộng đồng nói chung

Đó là nó. Bây giờ bạn có thể đọc tất cả các tham số cấu hình của mình và các giá trị tương ứng của chúng từ từ điển kết quả và sử dụng các tham số để thiết lập dự án trình soạn thảo của bạn

Phần kết luận

Bạn đã học cách sử dụng hàm

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 tích hợp để thực thi mã Python từ đầu vào chuỗi hoặc mã byte. Chức năng này cung cấp một công cụ nhanh chóng để thực thi mã Python được tạo động. Bạn cũng đã học cách giảm thiểu rủi ro bảo mật liên quan đến
>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 và khi nào thì có thể sử dụng hàm trong mã của mình

Trong hướng dẫn này, bạn đã học cách

  • Làm việc với hàm
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1 tích hợp sẵn của Python
  • Sử dụng
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1 của Python để chạy đầu vào dựa trên chuỗi và mã được biên dịch
  • Đánh giá và giảm thiểu rủi ro bảo mật liên quan đến việc sử dụng
    >>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
    >>> result
    84
    
    1

Ngoài ra, bạn đã mã hóa một số ví dụ thực tế giúp bạn hiểu rõ hơn về thời điểm và cách sử dụng

>>> exec["result = sum[number**2 for number in numbers if number % 2 == 0]"]
>>> result
84
1 trong mã Python của mình

Mã mẫu. Nhấp vào đây để tải xuống mã mẫu miễn phí mà bạn sẽ sử dụng để khám phá các trường hợp sử dụng cho hàm exec[]

Đánh dấu là đã hoàn thành

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Gửi cho tôi thủ thuật Python »

Giới thiệu về Leodanis Pozo Ramos

Leodanis là một kỹ sư công nghiệp yêu thích Python và phát triển phần mềm. Anh ấy là một nhà phát triển Python tự học với hơn 6 năm kinh nghiệm. Anh ấy là một nhà văn đam mê kỹ thuật với số lượng bài báo được xuất bản ngày càng tăng trên Real Python và các trang web khác

» Tìm hiểu thêm về Leodanis

Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Aldren

Geir Arne

Ian

kate

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. Nhận các mẹo để đặt câu hỏi hay và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Chủ Đề