Chuyển đến nội dung chính

if __name__ == "__main__" trong Python: Giải thích đầy đủ

Khối if __name__ == "__main__" trong Python cho phép bạn xác định đoạn mã chỉ chạy khi tệp được thực thi trực tiếp như một script, nhưng không chạy khi được import như một module vào script khác.
· 8 phút đọc

Khám phá cùng AI

Khối điều kiện bắt đầu bằng if __name__ == "__main__" xuất hiện thường xuyên trong mã Python. Dòng này có thể trông khó hiểu, và nhiều người mới học dùng nó mà không biết nó làm gì hoặc có nên dùng hay không. Lập trình viên chuyển từ ngôn ngữ khác sang cũng có thể hiểu sai và lạm dụng thành ngữ này.

Hướng dẫn này đi sâu vào ý nghĩa của thành ngữ Python if__name__ == "__main__" và khám phá cách dùng cũng như thời điểm nên dùng nó.

Tìm hiểu về __name__ và "__main__"

Thành ngữ if __name__ == "__main__" là một câu lệnh if kiểm tra tính bằng nhau.

Toán hạng thứ nhất ở bên trái toán tử so sánh bằng == là thuộc tính __name__. Các tên trong Python có dấu gạch dưới kép ở đầu và cuối là các định danh đặc biệt. Mọi module đều có thuộc tính __name__. Python gán biến này thành tên module, và hệ thống import của Python dùng để nhận diện duy nhất từng module.

Tuy nhiên, nếu module nằm trong môi trường mã cấp cao nhất (top-level), nghĩa là module đó được dùng làm điểm vào của chương trình, Python sẽ đặt thuộc tính __name__ thành chuỗi "__main__".

Hãy xem một vài ví dụ. Tạo một script tên là exploring_name_main.py:

# exploring_name_main.py
import random
print(__name__)
print(random.__name__)

Script này có thể chạy trực tiếp bằng lệnh sau trong terminal:

$ python exploring_name_main.py
__main__
random

Script exploring_name_main.py đang ở môi trường mã cấp cao nhất vì nó là điểm vào của chương trình. Do đó, biến __name__ được đặt thành chuỗi "__main__".

Trong khi đó, module random được import và không ở môi trường mã cấp cao nhất. Thuộc tính __name__ của nó được đặt thành tên module.

Tiếp theo, chúng ta tạo một script mới tên more_exploration.py, script này import script đầu tiên:

# more_exploration.py
import exploring_name_main

Chạy script này bằng lệnh sau trong terminal:

$ python more_exploration.py
exploring_name_main
random

Mã trong một module sẽ được thực thi khi module đó được import. Vì vậy, khi chạy more_exploration.py, chương trình hiển thị kết quả từ hai lệnh gọi print() trong exploring_name_main.py. Vì exploring_name_main.py không còn là điểm vào của chương trình nữa, thuộc tính __name__ của nó được đặt thành tên script thay vì "__main__".

Khối điều kiện if __name__ == "__main__"

Biến __name__ có thể được dùng để xác định liệu một module có phải là điểm vào chính của chương trình hay không. Do đó, một module có thể bao gồm mã chỉ được thực thi khi nó được chạy trực tiếp như một script, nhưng không chạy khi được import. Bất kỳ đoạn mã nào chỉ nên chạy khi script được chạy trực tiếp sẽ được đặt trong khối điều kiện if __name__ == "__main__":

# exploring_name_main.py
import random
print(__name__)
print(random.__name__)
number = random.randint(1, 10)
if __name__ == "__main__":
    print("This script is in the top-level code environment")
    print(f"The number is {number}")

Mã trong exploring_name_main.py giờ đã có thêm một khối điều kiện if __name__ == "__main__". Hãy xem điều này tạo khác biệt gì khi chạy script:

$ python exploring_name_main.py
__main__
random
This script is in the top-level code environment
The number is 10

Khi script được chạy trực tiếp, biến __name__ được đặt thành chuỗi "__main__". Do đó, điều kiện trong câu lệnh if được đánh giá là True, và Python thực thi mã trong khối if.

Tuy nhiên, khi module được import, __name__ được đặt thành tên module, và chương trình không thực thi khối if. Hãy nhớ rằng script more_exploration.py import exploring_name_main:

$  python more_exploration.py
exploring_name_main
random

Chương trình không gọi các hàm print() trong exploring_name_main.py. Chúng nằm trong khối điều kiện không được thực thi vì __name__ không bằng "__main__".

Thực hành tốt và mẹo khi dùng if __name__ == "__main__" trong Python

Thành ngữ if __name__ == "__main__" của Python được dùng khi mã chỉ nên được thực thi khi tệp được chạy như một script thay vì được import như một module. Sự khác biệt giữa thuật ngữ script và module chỉ nằm ở cách tệp được sử dụng. Cả hai đều là các tệp có phần mở rộng .py.

Một trường hợp sử dụng phổ biến là khi một script có các biến, hàm và lớp có thể được dùng trong chương trình khác. Đây là ví dụ với một script tên shapes.py:

# shapes.py
import math
def find_area_of_circle(radius):
    return math.pi * radius ** 2
def find_area_of_rectangle(width, height):
    return width * height
if __name__ == "__main__":
    shape = int(input("Enter 1 for circle, 2 for rectangle: "))
    if shape == 1:
        radius = int(input("Enter radius: "))
        print(f"The area of the circle is {find_area_of_circle(radius)}")
    elif shape == 2:
        width = int(input("Enter width: "))
        height = int(input("Enter height: "))
        print(f"The area of the rectangle is {find_area_of_rectangle(width, height)}")
Enter 1 for circle, 2 for rectangle: 2
Enter width: 10
Enter height: 20
The area of the rectangle is 200

Đoạn mã này không cần thành ngữ if __name__ == "__main__" nếu mục đích luôn là chạy nó như một script. Tuy nhiên, thêm câu lệnh điều kiện này cho phép mã được import như một module mà không thực thi các dòng trong khối if. Xem xét một script khác tên more_shapes.py:

# more_shapes.py
import shapes
radius = 5
print(f"The area of the circle defined in 'more_shapes.py' is: "
      f"{shapes.find_area_of_circle(radius)}")
The area of the circle defined in 'more_shapes.py' is: 78.53981633974483

Script mới này, more_shapes.py, có thể truy cập các hàm được định nghĩa trong shapes.py nhờ câu lệnh import. Tuy nhiên, mã trong khối if __name__ == "__main__" của shapes.py sẽ không được thực thi. Nếu không có câu lệnh if trong shapes.py, toàn bộ mã sẽ chạy khi module được import.

Dùng khối if __name__ == "__main__" cho việc nhập liệu từ người dùng là một trường hợp phổ biến. Việc nhập liệu sẽ bị lược bỏ nếu tệp được import như một module nhưng sẽ được thực hiện khi chạy trực tiếp dưới dạng mã cấp cao nhất.

Sử dụng hàm main()

Thực hành tốt là đưa vào khối if __name__ == "__main__" càng ít câu lệnh càng tốt để mã dễ đọc hơn. Cách làm phổ biến là tạo một hàm và gọi nó trong khối điều kiện. Thông thường hàm này được gọi là main(), nhưng bất kỳ tên hàm nào cũng hợp lệ:

# shapes.py
import math
def find_area_of_circle(radius):
    return math.pi * radius ** 2
def find_area_of_rectangle(width, height):
    return width * height
def main():
    shape = int(input("Enter 1 for circle, 2 for rectangle: "))
    if shape == 1:
        radius = int(input("Enter radius: "))
        print(f"The area of the circle is {find_area_of_circle(radius)}")
    elif shape == 2:
        width = int(input("Enter width: "))
        height = int(input("Enter height: "))
        print(f"The area of the rectangle is {find_area_of_rectangle(width, height)}")
       
if __name__ == "__main__":
    main()

Mã trong hàm main() giống hệt đoạn mã trước đó được đặt trực tiếp trong khối if __name__ == "__main__".

Trong Python, hàm main() không bắt buộc phải là điểm vào chính của chương trình, không giống một số ngôn ngữ lập trình khác. Vì vậy, việc dùng main() và thành ngữ if __name__ == "__main__" là tùy chọn, và chỉ cần khi mã được dự định dùng cả như một script độc lập lẫn như một module.

Một trường hợp phổ biến khác của if __name__ == "__main__" trong Python là thêm các bài kiểm thử vào script. Các kiểm thử sẽ chạy khi script được thực thi trực tiếp nhưng không chạy khi nó được import từ module khác. Tuy nhiên, dù cách này phù hợp cho các trường hợp đơn giản, tốt nhất là đặt kiểm thử trong một module riêng dành cho testing.

Kết luận

Trong Python, if __name__ == "__main__" hữu ích để đưa vào mã chỉ được chạy khi script được thực thi trực tiếp mà không chạy khi được import. Trình thông dịch Python đặt biến __name__ thành tên module nếu nó được import và thành chuỗi "__main__" nếu module là điểm vào chính của chương trình.

Không giống một số ngôn ngữ lập trình khác, hàm main() và thành ngữ if __name__ == "__main__" không phải là yêu cầu để chạy mã Python, mà là công cụ lập trình viên có thể sử dụng khi cần.

Stephen Gruppetta

Tác giả

Stephen Gruppetta

Tôi học Vật lý và Toán ở bậc đại học tại Đại học Malta. Sau đó, tôi chuyển đến London và lấy bằng Tiến sĩ Vật lý tại Imperial College. Tôi nghiên cứu các kỹ thuật quang học mới để chụp ảnh võng mạc người. Hiện nay, tôi tập trung vào việc viết về Python, truyền đạt về Python và giảng dạy Python.

Chủ đề

Liên quan