Gọi hàm động Python
Hàm 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 Show
Hàm 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 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ìnhTrong hướng dẫn này, bạn sẽ học cách
Ngoài ra, bạn sẽ viết một số ví dụ về cách sử dụng 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 PythonChức năng 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 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ẽ. 1 của Python giống như 02 nhưng thậm chí còn mạnh hơn và dễ gặp sự cố bảo mật. Trong khi 02 chỉ có thể đánh giá các biểu thức, thì 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, 1 có thể thực thi toàn bộ chương trình Python đầy đủ tính năngChữ ký của 1 có dạng như sau 5Hàm thực thi 07, 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ịchGhi 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 , đâ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à Python thực thi Nếu 07 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 07 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útCác đối số 90 và 91 cho phép bạn cung cấp từ điển đại diện cho và không gian tên trong đó 1 sẽ chạy mã đíchGiá trị trả về của hàm 1 là 94, 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 02, 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 1, bạn có thể tạo một trình thông dịch Python thô sơ với hai dòng mã>>> 6Trong ví dụ này, bạn sử dụng vòng lặp vô hạn 97 để bắt chước hành vi của Python hoặc REPL. Bên trong vòng lặp, bạn sử dụng để lấy đầu vào của người dùng tại dòng lệnh. Sau đó, bạn sử dụng 1 để xử lý và chạy đầu vàoVí dụ này giới thiệu những gì được cho là trường hợp sử dụng chính của 1. mã thực thi đến với bạn dưới dạng một chuỗiGhi chú. Bạn đã học được rằng việc sử dụng 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 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 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àyKhi 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 1 để thực thi chúng như cách bạn thực thi bất kỳ mã Python nàoTrong 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 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ạnTrong lập trình, một hàm như 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 1Tuy nhiên, với sức mạnh lớn đi kèm với trách nhiệm lớn. Hàm 1 hàm ý nghiêm trọng, bạn sẽ sớm học được. Vì vậy, bạn nên tránh sử dụng 1 hầu hết thời gianTrong các phần sau, bạn sẽ tìm hiểu cách thức hoạt động của 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ịchLoại bỏ các quảng cáoChạy mã từ đầu vào chuỗiCách phổ biến nhất để gọi 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
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 >>> 1Ở dòng được đánh dấu, bạn sử dụng a để 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 22 để tính tổng bình phươngĐể chạy mã này với 1, bạn chỉ cần chuyển đổi mã một dòng thành chuỗi một dòng>>>
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 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 1 trả về 94 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 mã 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 >>> 0Bạ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 1. Đây là cách>>> 9Ý 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, 28>>> 2Ký tự dòng mới làm cho 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 đó, 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òngCá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 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 >>> 2Trong 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 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 1 sẽ hiểu và thực thi chuỗi này như một tệp mã Python thông thườngBạn nên lưu ý rằng khi bạn chuyển một chuỗi có mã tới 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 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>>> 1Trong ví dụ này, mã đích chứa lệnh gọi tới 16 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, 1 đưa ra một 18 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ệnChạ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 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 thiTrong 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 1 nhiều lần nếu cần. Trong phần sau, bạn sẽ học cách sử dụng 1 với các đối tượng mã được biên dịchLoại bỏ các quảng cáoThực thi mã biên dịchTrong thực tế, 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. 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 1 để thực thiChữ ký của 03 có dạng như sau 0Trong hướng dẫn này, bạn sẽ chỉ sử dụng ba đối số đầu tiên cho 03. Đối số 07 giữ mã mà bạn cần biên dịch thành mã byte. Đối số 08 sẽ giữ tệp mà mã được đọc từ đó. Để đọc từ một đối tượng chuỗi, bạn sẽ phải đặt 08 thành giá trị 600Ghi 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 03, hãy xem thông tin chính thức của hàmCuối cùng, 03 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 1 hoặc 02, tùy thuộc vào giá trị của đối số 605. Đối số này phải được đặt thành 606 hoặc 607, tùy thuộc vào chức năng thực thi mục tiêu>>> 60Biên dịch trước mã thường lặp lại với 03 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 1Chạy mã từ tệp nguồn PythonBạn cũng có thể sử dụng 1 để chạy mã mà bạn đã đọc từ tệp 611 đá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 chức năng 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 chuỗi này làm đối số cho 1Ví dụ: giả sử bạn có tệp Python có tên 614 chứa đoạn mã sau 61Tậ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 615 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ìnhBâ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 >>> 62Trong ví dụ này, trước tiên bạn mở tệp 611 đích dưới dạng tệp văn bản thông thường bằng cách sử dụng hàm 612 tích hợp trong câu lệnh 618. Sau đó, bạn gọi đối tượng tệp để đọc nội dung của tệp vào biến 07. Lệnh gọi tới 619 này 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 1 với chuỗi này làm đối sốVí dụ này chạy mã và làm cho hàm 615 và các đối tượng sống trong 614 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 615. Bí mật đằng sau hành vi này liên quan đến các đối số 90 và 91 mà bạn sẽ tìm hiểu trong phần tiếp theoSử 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 628, 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 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áoSử dụng đối số >>> exec("result = sum(number**2 for number in numbers if number % 2 == 0)") >>> result 84 90 và >>> exec("result = sum(number**2 for number in numbers if number % 2 == 0)") >>> result 84 91Bạn có thể chuyển ngữ cảnh thực thi tới 1 bằng cách sử dụng đối số 90 và 91. 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à 1 sẽ sử dụng để chạy mã đíchCác đối số này là tùy chọn. Nếu bạn bỏ qua chúng, thì 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 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 1Xem xét ví dụ sau >>> 63Ví dụ này cho thấy rằng nếu bạn gọi 1 mà không cung cấp các giá trị cụ thể cho các đối số 90 và 91, 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ầuLưu ý rằng sau khi bạn gọi 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 642 ở dòng mã cuối cùngNếu bạn chỉ cung cấp một giá trị cho 90, thì giá trị đó phải là một từ điển. Hàm 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>>> 64Trong lần gọi đầu tiên tới 1, bạn sử dụng từ điển làm đối số 90. Vì từ điển của bạn không cung cấp khóa chứa tên 647, lệnh gọi tới 1 không có quyền truy cập vào tên này và phát sinh ngoại lệ 649Trong lần gọi thứ hai tới 1, bạn cung cấp một từ điển khác cho 90. Trong trường hợp này, từ điển chứa cả hai biến, 652 và 647, 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 642 sau cuộc gọi tới 1. Tại sao? Nếu bạn gọi 1 bằng một từ điển 90 không chứa khóa 659 một cách rõ ràng, thì Python sẽ tự động chèn một tham chiếu đến hoặc không gian tên 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>>> 65Trong ví dụ này, bạn đã cung cấp một từ điển trống cho đối số 90. Lưu ý rằng 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 659Nếu bạn cung cấp một giá trị cho đối số 91, thì đó có thể là bất kỳ đối tượng nào. Đối tượng ánh xạ này sẽ giữ không gian tên cục bộ khi 1 đang chạy mã mục tiêu của bạn>>> 66Cuộc gọi đến 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ố 90 cung cấp tên 652 từ phạm vi toàn cầu và đối số 91 cung cấp tên 647 từ phạm vi cục bộLưu ý rằng sau khi chạy 670, bạn không có quyền truy cập vào 642 vì tên này được tạo trong phạm vi cục bộ của 1, không có sẵn từ bên ngoàiVới các đối số 90 và 91, bạn có thể điều chỉnh ngữ cảnh trong đó 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 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úngKhá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 1Như bạn đã học cho đến nay, 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 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 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ácTrong 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 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 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 các từ điển rõ ràng 90 và 91Một vấn đề nghiêm trọng khác với 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 để 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átTrong 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 1 trong mã của mìnhLoại bỏ các quảng cáoTránh đầu vào từ các nguồn không đáng tin cậyNế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 1 để thực thi mã>>> 67Bâ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ư 689. Đ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 690 bằng cách tận dụng từ điển 90>>> 68Hệ thống 690 bên trong sử dụng chức năng 693 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 690 sẽ không hoạt độngMặc dù bạn có thể điều chỉnh từ điển 90 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 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àyHạn chế >>> exec("result = sum(number**2 for number in numbers if number % 2 == 0)") >>> result 84 90 và >>> exec("result = sum(number**2 for number in numbers if number % 2 == 0)") >>> result 84 91 để giảm thiểu rủi roBạn có thể cung cấp từ điển tùy chỉnh dưới dạng đối số 90 và 91 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 1. Ví dụ: nếu bạn chuyển các từ điển trống cho cả 90 và 91, thì 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>>> 69Nếu bạn gọi 1 với các từ điển trống cho 90 và 91, 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 1Tuy nhiên, kỹ thuật này không đảm bảo sử dụng an toàn 1. Tại sao? >>> 10Trong các ví dụ này, bạn sử dụng các từ điển trống cho 90 và 91, nhưng 1 vẫn có thể truy cập các hàm tích hợp sẵn như 115, 116 và 16. Làm thế nào bạn có thể ngăn chặn 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épNhư bạn đã biết, nếu bạn chuyển một từ điển tùy chỉnh cho 90 mà không có khóa 659, 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 659 mới. Để hạn chế hành vi tiềm ẩn này, bạn có thể sử dụng từ điển 90 chứa khóa 659 với giá trị phù hợpVí 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 1 như trong ví dụ sau>>> 11Trong ví dụ này, bạn đặt 90 thành một từ điển tùy chỉnh chứa khóa 659 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 90. Bằng cách này, bạn đảm bảo rằng 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ạnBạn cũng có thể điều chỉnh khóa 659 của mình nếu bạn chỉ cần 1 để truy cập một số tên tích hợp nhất định>>> 12Trong ví dụ đầu tiên, 1 chạy thành công mã đầu vào của bạn vì 115 và 16 có trong từ điển được liên kết với khóa 659. Trong ví dụ thứ hai, 1 tăng 649 và không chạy mã đầu vào của bạn vì 116 không có trong 138 được cung cấpCá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 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 1, hãy thử nghĩ ra một giải pháp khác không sử dụng hàmLoạ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 độngCho đến thời điểm này, bạn đã học được cách hoạt động của hàm 1 tích hợp. Bạn biết rằng bạn có thể sử dụng 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, 90 và 91, cho phép bạn điều chỉnh không gian tên thực thi cho 1Ngoài ra, bạn đã biết rằng việc sử dụng 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 1 trong mã của bạnTrong 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 1 có thể phù hợpChạy mã từ các nguồn bên ngoàiSử dụng 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 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 địnhBạn không bao giờ được sử dụng 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 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 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 mà Guido van Rossum đã tự viết ban đầuMô-đun 155 cung cấp một cách nhanh chóng để đị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>>> 13Hàm 157 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ụ: 158 cho phép bạn cung cấp số lần bạn muốn thực thi mã mục tiêuTại trung tâm của chức năng này, bạn sẽ tìm thấy lớp. 159 sử dụng 1 để chạy mã được cung cấp. Nếu bạn kiểm tra mã nguồn của 159 trong mô-đun 155, thì bạn sẽ thấy rằng lớp , 164, bao gồm mã sau 14Cuộc gọi đến 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 166 và 167 làm không gian tên toàn cầu và cục bộ của nóCách sử dụng 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ànMột ví dụ khác về việc sử dụng 1 để chạy mã ở dạng chuỗi là mô-đun 170. 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 170 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ôngVí dụ: giả sử bạn có hàm sau để cộng hai số với nhau 15Trong đoạn mã này, 172 xác định 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 172 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 170 để chạy chúng và kiểm tra xem chúng có đưa ra kết quả như mong đợi khôngGhi 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 175 của bạn 16Lệ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 170 sử dụng 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 17Như 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 1, sử dụng 03 để biên dịch mã đích. Để chạy mã này, 1 sử dụng 181 làm đối số 90 của nó. Lưu ý rằng nhận xét ngay trước lệnh gọi tới 1 nói đùa rằng đây là nơi mã của người dùng chạyMột lần nữa, trong trường hợp sử dụng của 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ì 170 không chịu trách nhiệm đảm bảo rằng cuộc gọi tới 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à 170 không ngăn chặn các rủi ro bảo mật liên quan đến 1. Nói cách khác, 170 sẽ chạy bất kỳ mã Python nào. Ví dụ: ai đó có thể sửa đổi hàm 172 của bạn để đưa đoạn mã sau vào chuỗi tài liệu 18Nếu bạn chạy 170 trên tệp này, thì lệnh 192 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ư 193 hoặc bất kỳ lệnh nguy hiểm nào khácMột lần nữa, bạn luôn phải cẩn thận với 1 và với các công cụ sử dụng chức năng này, chẳng hạn như 170. Trong trường hợp cụ thể của 170, 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 íchLoại bỏ các quảng cáoSử dụng Python cho tệp cấu hìnhMột tình huống khác mà bạn có thể sử dụng 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 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úngVí 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 19Tệ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 1 như cách bạn thực hiện với tệp 611 thông thườngGhi 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 1. Trong thư viện chuẩn Python, bạn có mô-đun, cho phép bạn xử lý các tệp cấu hình sử dụng định dạng tệp INIHàm bên dưới đọc tệp 03 của bạn và xây dựng từ điển cấu hình>>> 0Hàm 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 1 để thực thi. Trong quá trình chạy 1, hàm đưa các tham số cấu hình vào từ điển 91, từ điển này sau đó được trả về mã người gọiGhi chú. Kỹ thuật trong phần này có lẽ là trường hợp sử dụng an toàn của 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ảnNế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ậnBạn đã học cách sử dụng hàm 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 1 và khi nào thì có thể sử dụng hàm trong mã của mìnhTrong hướng dẫn này, bạn đã học cách
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 1 trong mã Python của mìnhMã 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ề LeodanisMỗ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 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ẻ EmailBà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. 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 Các lệnh gọi hàm động là gì?Các lệnh gọi hàm động hữu ích khi bạn muốn thay đổi luồng chương trình theo hoàn cảnh thay đổi . Ví dụ: chúng tôi có thể muốn tập lệnh của mình hoạt động khác theo một tham số được đặt trong chuỗi truy vấn của URL. Chúng ta có thể trích xuất giá trị của tham số này và sử dụng nó để gọi một trong số các chức năng.
Bốn cách gọi hàm khác nhau trong Python là gì?Trong python, chúng ta có thể gọi một hàm bằng 4 loại đối số. . Đối số bắt buộc đối số từ khóa Đối số mặc định Đối số có độ dài thay đổi Ví dụ hàm động là gì?Hàm động là một cách gọi hàm động một cách linh hoạt . Trình biên dịch sẽ có kiến thức hạn chế về những gì bạn đang làm, do đó bạn sẽ gặp lỗi thời gian chạy nếu bạn không sử dụng đầu vào và đầu ra chính xác. Một ví dụ chạy các chức năng khác nhau tùy thuộc vào đầu vào của người dùng. XÁC ĐỊNH iFunc BIẾN NHƯ SỐ SỐ KHÔNG HOÀN TÁC.
Làm cách nào để gọi hàm từ tên được lưu trong chuỗi bằng Python?Để gọi hàm theo tên chuỗi. Nhập mô-đun chức năng được xác định trong. Sử dụng hàm getattr() để lấy hàm . |