exec Python: Khi code tự biết 'nhảy múa' theo ý bạn!
Python

exec Python: Khi code tự biết 'nhảy múa' theo ý bạn!

Author

Admin System

@root

Ngày xuất bản

20 Mar, 2026

Lượt xem

4 Lượt

exec

Chào các 'nghệ nhân' code tương lai của nhà Creyt! Hôm nay, chúng ta sẽ 'phá đảo' một khái niệm mà nghe qua thì 'cool ngầu' nhưng dùng không cẩn thận thì 'toang' ngay. Đó là exec trong Python. Nghe tên đã thấy nó muốn 'hành động' rồi đúng không?

1. exec là gì mà 'ghê gớm' vậy?

Thực ra, exec trong Python không phải là một phép thuật gì đó quá xa vời, nó đơn giản là một hàm cho phép bạn thực thi các câu lệnh Python (statements) được cung cấp dưới dạng một chuỗi (string). Tưởng tượng thế này: bạn đang ngồi viết code, nhưng có một đoạn code khác lại nằm 'lơ lửng' đâu đó dưới dạng văn bản. Thay vì phải chép tay hay copy-paste, bạn chỉ cần ném cái chuỗi văn bản đó vào exec, và 'tách!', Python sẽ coi nó như code thật và chạy ngon ơ.

Nói theo Gen Z thì, exec giống như bạn có một cái AI 'siêu thông minh' có thể đọc được bất kỳ 'kịch bản' nào bạn đưa cho nó (miễn là kịch bản đó viết bằng ngôn ngữ của nó - Python) và tự động diễn xuất theo kịch bản đó ngay lập tức, không cần bạn phải 'compile' hay 'deploy' gì hết. Siêu 'instant' luôn!

Để làm gì ư? Đôi khi, bạn cần code của mình có khả năng tự thay đổi hoặc chạy những thứ mà bạn không biết trước khi chương trình khởi động. Ví dụ, bạn muốn người dùng có thể tùy chỉnh hành vi của ứng dụng bằng cách viết một đoạn code nhỏ, hoặc bạn đang xây dựng một hệ thống plugin mà các plugin đó được tải và chạy 'on-the-fly'. exec chính là 'chìa khóa vạn năng' cho những tình huống này.

2. Code Ví Dụ Minh Hoạ: 'Ảo thuật' code trong tầm tay

Anh Creyt biết, nói suông thì 'khô như ngói', phải có code mới 'thấm'. Đây là ví dụ 'nhẹ nhàng tình cảm' để các bạn thấy exec hoạt động thế nào:

print("--- Ví dụ 1: Cơ bản nhất ---")
code_string_1 = "print('Hello từ code động của exec!')"
exec(code_string_1)

print("\n--- Ví dụ 2: Tạo biến và hàm 'on-the-fly' ---")
code_string_2 = """
spam = 'trứng ốp la'
def greet(name):
    print(f'Chào bạn {name}, bạn có thích {spam} không?')
"""
exec(code_string_2)

# Giờ thì có thể dùng biến và hàm vừa tạo
print(f"Biến spam vừa tạo là: {spam}")
greet("Genz Dev")

print("\n--- Ví dụ 3: Giới hạn phạm vi (scope) với globals và locals ---")
# Khi exec, nó sẽ dùng scope hiện tại (globals() và locals() của hàm gọi nó)
# Nhưng bạn có thể truyền vào các dictionary riêng để kiểm soát

my_globals = {'__builtins__': None} # Không cho phép truy cập hàm built-in nào
my_locals = {'x': 10, 'y': 20}

exec("z = x + y", my_globals, my_locals)
# z đã được tạo trong my_locals, không phải trong scope hiện tại
print(f"Giá trị của z trong my_locals: {my_locals['z']}")

try:
    print(z) # Sẽ báo lỗi vì z không tồn tại trong scope hiện tại
except NameError as e:
    print(f"Lỗi: {e} (z không tồn tại trong scope này)")

# Ví dụ về việc không cho phép built-in
code_string_dangerous = "import os; print(os.getcwd())"
try:
    exec(code_string_dangerous, {'__builtins__': {}})
except NameError as e:
    print(f"\nLỗi: {e} (Không cho phép dùng 'import' do __builtins__ bị giới hạn)")

Thấy chưa? exec nó biến một chuỗi thành code 'sống' ngay lập tức. Trong ví dụ 2, chúng ta tạo biến spam và hàm greet từ một chuỗi, sau đó dùng chúng như thể đã định nghĩa từ đầu. Còn ví dụ 3 cho thấy bạn có thể 'khoanh vùng' quyền lực của exec bằng cách cung cấp globalslocals riêng, đây là một mẹo cực kỳ quan trọng để giữ an toàn!

Illustration

3. Mẹo (Best Practices) để 'chơi' với exec mà không 'bay màu'

  • An toàn là bạn, tai nạn là thù (Security First!): Đây là điều quan trọng nhất. TUYỆT ĐỐI KHÔNG DÙNG exec với chuỗi code đến từ nguồn không đáng tin cậy (ví dụ: input của người dùng, dữ liệu từ mạng). Nó giống như bạn đưa chìa khóa nhà cho một người lạ vậy. Họ có thể làm bất cứ điều gì, từ xóa file, đọc dữ liệu nhạy cảm cho đến cài mã độc. Hãy coi exec như một khẩu súng 'lục' – cực kỳ uy lực nhưng cũng cực kỳ nguy hiểm nếu không biết cách dùng.
  • Giới hạn phạm vi (Scope Control): Như ví dụ 3, hãy tận dụng các đối số globalslocals của exec. Bạn có thể truyền vào các dictionary trống hoặc chỉ chứa những thứ bạn muốn code động truy cập. Đặc biệt, hãy xét đến việc đặt __builtins__ thành một dictionary trống hoặc chỉ chứa một vài hàm an toàn để ngăn chặn việc gọi các hàm hệ thống nguy hiểm.
  • Khi nào dùng, khi nào tránh: exec rất mạnh, nhưng không phải lúc nào cũng là giải pháp tốt nhất. Nếu bạn chỉ cần đánh giá một biểu thức (expression) và lấy kết quả, hãy dùng eval(). Nếu bạn cần tải module động, importlib là lựa chọn an toàn và rõ ràng hơn. Chỉ dùng exec khi bạn thực sự cần chạy các câu lệnh (statements) Python được tạo ra trong quá trình chạy chương trình và không có cách nào khác tốt hơn.
  • Đọc code động trước khi chạy: Nếu chuỗi code động của bạn được tạo ra trong nội bộ chương trình, hãy đảm bảo rằng bạn đã kiểm tra kỹ lưỡng logic tạo chuỗi đó để tránh những lỗi hoặc lỗ hổng không mong muốn.

4. Ứng dụng thực tế: exec và những 'người anh em' của nó

Trong thực tế, việc dùng exec trực tiếp có thể không phổ biến ở các ứng dụng web thông thường vì lý do bảo mật. Tuy nhiên, ý tưởng về việc chạy code động lại được ứng dụng rộng rãi:

  • Hệ thống Plugin/Module: Các ứng dụng lớn như IDE (PyCharm, VS Code) hay các framework (Django, Flask) thường có hệ thống plugin hoặc cách để bạn mở rộng chức năng bằng cách viết thêm code. Mặc dù không dùng exec trực tiếp, nhưng cơ chế tải và thực thi các module mới được viết bởi người dùng (dù đã được kiểm soát) có chung 'tư tưởng' là chạy code không có sẵn từ đầu.
  • Tùy biến cấu hình động: Một số hệ thống cho phép người dùng viết các đoạn script nhỏ để tùy chỉnh hành vi. Ví dụ, trong các công cụ tự động hóa, bạn có thể viết một script Python nhỏ để định nghĩa các bước xử lý.
  • Interactive Shell (Python REPL): Khi bạn gõ lệnh vào python trong terminal, nó chính là một môi trường exec (và eval) liên tục, thực thi từng dòng lệnh bạn nhập vào.
  • Jupyter Notebooks: Tương tự như REPL, mỗi cell trong Jupyter Notebook về cơ bản là một khối code được exec trong một môi trường nhất định.

5. Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào

Anh Creyt đã từng 'thử thách' với exec trong một dự án nhỏ về hệ thống báo cáo tùy chỉnh. Người dùng có thể định nghĩa các công thức tính toán phức tạp bằng cú pháp Python trong một file cấu hình. Thay vì phải viết một parser riêng, anh đã dùng exec để chạy các công thức đó. Nó hoạt động 'ngon lành cành đào', tiết kiệm rất nhiều thời gian.

Khi nào nên dùng (và cân nhắc kỹ):

  • Hệ thống plugin nội bộ, đáng tin cậy: Khi bạn xây dựng một framework và muốn người dùng có thể mở rộng chức năng bằng cách cung cấp các module Python, và bạn hoàn toàn kiểm soát nguồn gốc của các module đó.
  • Tùy chỉnh hành vi ứng dụng từ file cấu hình an toàn: Khi file cấu hình được tạo hoặc kiểm soát hoàn toàn bởi bạn và không có nguy cơ bị người ngoài chỉnh sửa. Ví dụ, một file .py chứa các hàm tùy chỉnh cho một tác vụ nội bộ.
  • Môi trường Sandbox có kiểm soát chặt chẽ: Khi bạn muốn cho phép người dùng chạy code, nhưng bạn đã xây dựng một 'sandbox' cực kỳ chặt chẽ bằng cách giới hạn globals, locals__builtins__ đến mức tối thiểu, chỉ cho phép các thao tác an toàn.
  • Công cụ nội bộ, không tiếp xúc với người dùng cuối: Viết các script tự động hóa, công cụ dev-ops mà chỉ những người có quyền truy cập hệ thống mới có thể chỉnh sửa code.

Khi nào TUYỆT ĐỐI KHÔNG NÊN DÙNG:

  • Input từ người dùng không đáng tin cậy: Bất kỳ chuỗi nào mà người dùng có thể nhập vào hoặc chỉnh sửa đều là một 'quả bom hẹn giờ' nếu bạn ném nó vào exec.
  • Dữ liệu từ mạng không được kiểm soát: Tương tự, dữ liệu nhận được từ API, web scraping, hay bất kỳ nguồn nào trên internet mà bạn không hoàn toàn tin tưởng.
  • Khi có giải pháp an toàn hơn: Nhớ lại, eval cho biểu thức, importlib cho module. Nếu có cách khác, hãy dùng nó!

exec là một con dao hai lưỡi, nó mạnh mẽ đến mức có thể 'phá hủy' cả hệ thống nếu không được dùng đúng cách. Hãy là những 'phù thủy' code thông thái, biết dùng phép thuật đúng lúc, đúng chỗ và luôn luôn đặt an toàn lên hàng đầu nhé các bạn Gen Z!

Thuộc Series: Python

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!