Ý nghĩa của if __name__ == '__main__': trong Python?

Hi mọi người,
Mình bắt đầu đọc quyển python network programming cookbook, có đoạn này mình không hiểu, mọi người giúp đỡ :smile:

import socket
def print_machine_info():
    host_name = socket.gethostname()
    ip_address = socket.gethostbyname(host_name)
    print "Host name: %s" % host_name
    print "IP address: %s" % ip_address
if __name__ == '__main__':
    print_machine_info()

Cái đoạn

if __name__ == '__main__':
  print_machine_info()

Nó có ý nghĩa gì thế ? khi mình chạy file python với nội dung như trên thì nó báo : name chưa được định nghĩa.
Anh em giúp mình với :smile:

6 Likes

Tại sao code trên không chạy được?

Là vì bạn indent, hay nói cách khác là cách đầu dòng, vào bị sai rồi. Phải viết lại như thế này. Đạt chạy ổn :smile:

import socket
def print_machine_info():
    host_name = socket.gethostname()
    ip_address = socket.gethostbyname(host_name)
    print "Host name: %s" % host_name
    print "IP address: %s" % ip_address
    
if __name__ == '__main__':
    print_machine_info()

Kết quả trả ra:

Host name: DatAsus
IP address: 192.168.56.101


Tại sao nên sử dụng điều kiện if này?

Về ý nghĩa của nó thì nó giống như các C và các ngôn ngữ khác bắt đầu một chương trình. Ta cần có một điểm để bắt đầu. Thì khi ta viết if __name__ == '__main__': thì Python sẽ thực thi phần lệnh phía sau của lệnh if nếu file này được thực thi bằng lệnh python. Đây là một phong cách lập trình của Python mà ta nên sử dụng.


Tại sao ta làm được như thế?

Lý do bên dưới của kỹ thuật này là khi Python interpreter đọc qua code Python thì nó sẽ chạy tất cả những lệnh mà nó thấy, từ trên xuống dưới.

Ví dụ nếu ta viết như sau thì nó sẽ in ra day nhau hoc

print "day",
print "nhau",
print "hoc"

Nhưng trước khi chạy những dòng code này Python Interpreter sẽ định nghĩa một số biến đặc biệt, trong đó có biến __name__. Nếu biến __name__ này thuộc về một module mà ta include, trong ví dụ dưới đây Đạt có một file daynhauhoc.py và file này include module whileloop, thì biến __name__ này sẽ được gán bằng tên của module đó.

Trong file daynhauhoc.py ta include whileloop

import whileloop

Trong file whileloop.py ta có dòng này

print "__name__ of whileloop.py is %s" % __name__

Thì kết quả khi chạy file daynhauhoc.py ta sẽ được

__name__ of whileloop.py is whileloop

Nếu biến __name__ này nằm trong file mà ta chạy trực tiếp bằng lệnh python. Thì Python Interpreter, tức trình thông dịch của Python, sẽ gán __name__ bằng __main__. Nếu ta thêm dòng này vào file daynhauhoc.py

print "__name__ of daynhauhoc.py is %s" % __name__

Thì ta sẽ có toàn bộ output là

__name__ of whileloop.py is whileloop
__name__ of daynhauhoc.py is __main__

Tham khảo: http://stackoverflow.com/a/419185/1989112

11 Likes

Wow, giờ đọc kĩ lại mới thấy thú vị nè :smile:

Tức là với chiêu này ta có thể “khóa” 1 đoạn code trong file chính lại khi nó được import bởi một file khác. Đoạn code bị khóa đó chỉ chạy khi file chính được mở trực tiếp :smile: => có thể tái sử dụng hàm trong file chính và test hàm thẳng từ trong module mà không sợ ảnh hưởng kết quả khi chạy file chính ( có import cái module đó) :smile:

3 Likes

:cry: khả năng đọc hiểu của em kém quá. Bác giải thích đơn giản hơn được không ạ ? lấy ví dụ từ hình kia luôn, bác giải thích cho em với. Mông rung à mà nhầm mông lung quá à :joy:

__name__ là một biến đặc biệt. Nếu biến này nằm trong một file python bất kỳ. Giả dụ ta có file daynhauhoc.py, thì khi ta chạy

python daynhauhoc.py

__name__ sẽ có giá trị __main__

Hiểu tới đây được rồi :smile:

3 Likes

Cái đấy thì em hiểu rồi anh ạ :smile: còn đoạn cmt của bác @thanhmssl10 thì em chưa hiểu lắm :smile:

1 Like

À, tức là em đang nói tới phần comment của @thanhmssl10?

Còn câu trả lời của anh có trả lời được câu hỏi đầu tiên của em chưa?

4 Likes

Hiểu đơn giản là biến __name__ là một biến được tự động sinh ra trong mỗi một file .py có giá trị bằng đúng tên của file .py đó. `Dạng name.py => Ví dụ: daynhauhoc.py có chứa name = “daynhauhoc”``

Biến __main__ là một biến được tự động sinh ra khi một process python được chạy. Nó có giá trị bằng đúng tên của file đang chiếm quyền thực thị.

Việc sử dụng kĩ thuật trên dùng để xác định xem đoạn code có được chạy trong file đang chiếm quyền thực thi hay không. Hay là chạy thông qua việc được import và được gọi đến bởi file đang chiếm quyền thực thị.

Hi vọng là nó có thể giúp bạn hiểu.

7 Likes

Em hiểu rồi anh ạ, anh giải thích rất rõ ràng. Lần này chưa tìm kỹ đã hỏi, ngại quá :frowning:

Vậy em check vào accept câu trả lời của anh đi :smile:


@GDGHN_AndroidTeam hình như có chút nhầm lẫn, theo Đạt biết, __main__ không phải là biến

2 Likes

Giờ mới để ý có nút accept :smile:

Cái của @thanhmssl10 ý là bạn có thể viết luôn code unit test trong chính cái file A. Và code test này sẽ chỉ chạy khi bạn chạy trực tiếp file A thôi. Khi có file B khác sử dụng đến nó, nó sẽ không thực thi các đoạn code unit test.
=> Không ảnh hưởng đến luồng xử lí của các file B đang gọi đến file A dù cho trong A có code Unit test (Đoạn code unit test chỉ nên dùng với A thôi, B không cần)

Điều này có gì tốt: Nếu Java ta cần 1 file chạy và 1 file unit test thì python không cần. Tất cả được cho vào một chỗ mà vẫn không bị ảnh hưởng đến những file khác sẽ sử dụng đến nó.

1 Like

Chết thật. Trước giờ cứ hiểu sai… Hi hi…

3 Likes

Cho mình hỏi, tại sao mình chạy file : tên là 123.py
Với nội dung là : print _name
Thì kết quả lại ra : main
Chứ không phải là “123” ?

Ý mình là theo anh này giải thích thì name = tên file
chứ không phải =main

Nói đơn giản: ví dụ bạn có mymodule.py
Khi bạn gọi mymodule.py từ một module khác:

import mymodule

thì __name__ sẽ là mymodule

Nếu bạn gọi từ console (run mymodule.py)
python mymodule.py

thì __name__ sẽ là __main__

1 Like

Câu trả lời tốt nhất!

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?