หลาย ๆ คนที่ศึกษา กำลังศึกษาหรือเรียนไพธอน มักจะเจอโค้ด if __name__ == '__main__': นี้กันอยู่เป็นประจำ ซึ่งทำให้เราปวดหัวและยังงงงวยกับเจ้าโค้ดนี้ และแน่นอนว่าหลายคนยังไม่รู้ว่า โค้ดภาษาไพธอนตรงส่วนนี้ทำหน้าที่อะไรกันแน่ และบทความสอนเกี่ยวกับเรื่องนี้ในไทยยังมีค่อนข้างน้อยไปจนถึงน้อยมาก เลยขอเขียนบทความนี้ขึ้นมา หวังว่าคงเป็นประโยชน์ไม่มากก็น้อย และในบทความนี้จะมาไขข้อข้องใจให้หายสงสัยกันครับ
ก่อนที่จะเข้าสู่ไฮไลท์ของเรื่อง จะขออธิบายเกี่ยวกับโมดูลและแพ็คเกจในภาษาไพธอนกันก่อนแบบภาพรวม จริง ๆ แล้ว Module ก็คือ Python File ส่วน Package ก็คือ Folder ที่เก็บโมดูลนั่นเอง โดยแพ็คเกจนั้นจะมีไฟล์ __init__.py กำหนดไว้ในโฟลเดอร์นั้น ๆ เพื่อบ่งบอกว่าโฟลเดอร์นี้คือ Package นั่นเอง โดยการเข้าถึง module และ package ก็จะขึ้นอยู่กับลำดับชั้นไฟล์และแพ็คเกจนั้น ๆ (File and Package Hierarchy) ขอยกตัวอย่างดังภาพด้านล่าง
(Photo: Basic Python คอร์ส - STACKPYTHON)
และด้านล่างคือการจัดวางไฟล์และการอิมพอร์ตในรูปแบบต่าง ๆ ตามระดับของโมดูลและแพ็คเกจที่ถูกจัดวางไว้ในโปรเจคท์
การจัดวาง Package และ Module (Photo: Basic Python คอร์ส - STACKPYTHON)
"ในบทความนี้จะไม่ได้อธิบาย Module และ Package แบบละเอียดยิบ โดยจะแยกเป็นบทความในเรื่องนี้แบบเฉพาะและจะเขียนในบทความต่อ ๆ ไป แต่ก็เชื่อว่าในบทความนี้ หลาย ๆ คนคงจะเข้าใจเกี่ยวกับโมดูลและแพ็คเกจได้เป็นอย่างดีและมองภาพรวมกันออกในเบื้องต้นกันครับ"
ลองมาทดสอบเขียนโค้ดอีกสักหน่อยเพื่อทำความเข้าใจเพิ่มเติม
tutorial1.py
#tutorial.py
print("Hello, this is a Python tutorial from STACKPYTHON")
ซึ่งจากโค้ดด้านบนนั้นมีการตั้งชื่อไฟล์ว่า tutorial.py และก็ไม่ได้มีคำสั่งอะไรมากมาย แสดงผลเพียงแค่คำสั่ง print("Hello, this is a Python tutorial from STACKPYTHON") ซึ่งเจ้าไฟล์นี้แหละก็คือโมดูลอย่างสมบูรณ์แบบด้วยตัวมันเอง ถึงตรงนี้หลายคนเริ่มพอจะมองภาพออกแล้ว ดังนั้นขอเสริมให้ชัดขึ้นไปอีก
ทำการสร้างไฟล์ขึ้นมาอีกหนึ่งไฟล์ที่มีชื่อว่า tutorial2.py
tutorial2.py
import tutorial1
print("Hello, This is the second Python file, tutorial2")
จากโค้ดด้านบนในไฟล์ tutorial2.py นั้นจะสามารถเรียกได้ว่า ได้ทำการอิมพอร์ตโมดูล tutorial1 มาใช้งาน ซึ่งการเรียกโมดูลนี้จะไม่ได้เรียก .py ซึ่งเป็นนามสกุลของไฟล์เข้าเกี่ยวข้องแล้ว และเมื่อรันโค้ดจะได้ผลลัพธ์ดังนี้
Output
Hello, this is a Python tutorial from STACKPYTHON
Hello, This is the second Python file, tutorial2
ซึ่ง Hello ในบรรทัดแรกจะเป็นผลลัพธ์มาจากคำสั่ง print("Hello, this is a Python tutorial from STACKPYTHON") ในโมดูล tutorial1 ซึ่งจะถูกรันก่อน เพราะได้ถูกอิมพอร์ตเข้ามาในส่วนบนสุดของไฟล์ tutorial2.py ซึ่งแน่นอนว่าโดยปกติแล้วโค้ดนั้นจะทำงานตามลำดับ จากซ้ายไปขวาและบนลงมาล่างเสมอ
สรุปได้ว่า
หลังจากทำความเข้าใจพื้นฐานก่อนหน้าที่ควรรู้ก็คือโมดูลมาเรียบร้อยแล้ว คราวนี้ก็ถึงไฮไลท์สำคัญของบทความนี้กันแล้ว โดยปกตินั้น __name__ จะเปรียบเสมือนตัวแปรตัวแปรหนึ่งของไพธอน แต่เป็นตัวแปรชนิดพิเศษสังเกตได้อีกทางหนึ่งคือมี Dunder หรือ เครื่องหมาย Double Underscores (Name Mangling) อยู่ในเมธอดหรือตัวแปรนั้น เช่น Dunder Methods เหล่านี้ __init__() , __str__() etc
โดยปกติถ้าเราทำการรันไพธอนไฟล์ไหน ไฟล์นั้นก็จะหลายเป็น main ไฟล์ หรือ '__main__' โดยอัตโนมัติ
แต่เดี๋ยวก่อน อย่าเพิ่งเชื่อถ้ายังไม่ได้พิสูจน์ โดยอันดับแรกให้ทำการสร้างไฟล์ขึ้นมาสองไฟล์มีชื่อว่า mod1.py และ mod2.py
mod1.py
# mod1.py
def func1():
print(f"This is mod1.py, and it is {__name__} module")
func1()
สังเกตตรง {__name__} จะเห็นว่านี่ก็คือตัวแปร ๆ หนึ่งเพราะชัดเจนว่าสามารถอยู่ใน { } ซึ่งเป็นไวยากรณ์ของไพธอนในรูปแบบของ f-string ที่เราสามารถแสดงผลข้อความโดยใช้ฟังก์ชัน print() ตามปกติ เพียงแต่ว่ารูปแบบนี้จะทำให้สะดวกและอ่านง่ายกว่า (ในความคิดเห็นของผู้เขียน) จากนั้นทำการรันโค้ดตามปกติ
Output
This is mod1.py, and it is __main__ module
สังเกตผลลัพธ์หลังจากรันโค้ดเสร็จ จะพบว่าโมดูลนี้คือ main module ถูกต้องตามที่ได้อธิบายไปก่อนหน้านี้
จากนั้นทำการสร้างไฟล์ที่สองขึ้นมาที่มีชื่อว่า mod2.py
mod2.py
import mod1
def func2():
print(f"This is mod2.py, and it is {__name__} module")
func2()
โดยในไฟล์ mod2.py นี้จะมีการอิมพอร์ต import mod1 โมดูลเข้ามาใช้งานด้วย จากนั้นให้ทำการรันโค้ด
Output
This is mod1.py, and it is mod1 module
This is mod2.py, and it is __main__ module
อธิบายสั้น ๆ แบบกระชับได้ดังนี้
ทดสอบใช้ if __name == '__main__':
ให้ทำการแก้ไขไฟล์ทั้ง 2 ไฟล์ โดยเปลี่ยนแปลงโค้ดดังนี้
mod1.py
def func1():
print(f"This is mod1.py, and it is {__name__} module")
def second_func_mod1():
print(f"This is the second function from mod1.py")
func1()
second_func_mod1()
ในส่วนของ mod1.py ไฟล์หรือสคริปต์นี้จะเป็นการรันและมีการประกาศและเรียกใช้งานฟังก์ชันทำงานตามปกติ ซึ่งก็จะได้ผลลัพธ์ตามปกติ
Output 1
This is mod1.py, and it is __main__ module
This is the second function from mod1.py
mod2.py
import mod1
print("Running code on mod2 now")
def func2():
print(f"This is mod2.py, and it is {__name__} module")
def second_func_mod2():
print(f"This is the second function from mod2.py")
if __name__ == '__main__':
pass
ในส่วนของ mod2.py จะมีการกำหนดเงื่อนไขเพิ่มเติมคือถ้าในไฟล์นี้คือ main ไฟล์ให้ทำการรัน Statement หรือโค้ดด้านล่าง ซึ่งสามารถกำหนดว่าจะให้ทำอะไรได้ตามต้องการ โดยในโค้ดนี้จะยังไม่ทำอะไร โดยทำการใส่ pass ซึ่งเป็น Python Keyword อีกตัวหนึ่งที่ใส่ไว้เพื่อไม่ให้โค้ดในส่วนนี้ว่าง ป้องกัน error ทำให้โปรแกรมยังทำงานต่อไปได้นั่นเอง
โดยโค้ดด้านบนจะได้ผลลัพธ์คล้ายคลึงกันกับ mod1.py เพียงแต่ว่า นอกจากเพิ่มเงื่อนไขให้รันถ้าไฟล์นี้เป็น main ไฟล์แล้วนั้น ก็ได้ทำการเพิ่มโค้ดเข้าอีกหนึ่งส่วนอยู่ด้านบนนั่นก็คือ print("Running...") และเมื่อสังเกตผลลัพธ์ก็จะพบว่า ได้มี Output เพิ่มมาอีก 1 แถว นั่นก็คือ Running code on mod2 now ต่อท้ายจากผลลัพธ์ของโค้ดที่อิมพอร์ตเข้ามาจาก import mod1
Output 2
This is mod1.py, and it is mod1 module # mod1
This is the second function from mod1.py # mod1
Running code on mod2 now # mod2
if else คือ Control Statement ซึ่งเมื่ออ่านถึงตรงนี้คงเข้าใจกันดีแล้ว ดังนั้นเราสามารถที่จะควบคุม Statement หรือการกระทำต่าง ๆ ได้ตามต้องการ โดยสังเกตได้ดังโค้ดในโค้ดด้านล่างและสามารถปรับเปลี่ยนได้ตามต้องการ
mod2.py
import mod1
print("Running code on mod2 now")
def func2():
print(f"This is mod2.py, and it is {__name__} module")
def second_func_mod2():
print(f"This is the second function from mod2.py")
# New
if __name__ == '__main__':
print('')
func2()
second_func_mod2()
else:
pass
Output 3
This is mod1.py, and it is mod1 module
This is the second function from mod1.py
Running code on mod2 now
This is mod2.py, and it is __main__ module
This is the second function from mod2.py
สร้างไฟล์ขึ้นมาใหม่ซึ่งเป็นไฟล์สุดท้ายชื่อว่า main.py main.py และทำการอิมพอร์ตทั้ง mod1 และ mod2 เข้ามาใช้งาน
main.py
import mod2
import mod1
print('')
print("Hope you enjoy reading this article")
และเมื่อสังเกตที่ผลลัพธ์นั้นในส่วนของฟังก์ชัน print('') , func1() และ
second_func_mod2() จะไม่ทำงานเนื่องจากว่าฟังก์ชันเหล่านี้กำหนดให้ทำงานในไฟล์ mod2.py เท่านั้น ซึ่งจะรันก็ต่อเมื่อเป็น main ไฟล์ แต่ตอนนี้ main คือ main.py ซึ่งได้ถูกสร้างขึ้นมาใหม่ล่าสุด
Output 4
This is mod1.py, and it is mod1 module
This is the second function from mod1.py
Running code on mod2 now
Hope you enjoy reading this article
จะขอยกกรณีตัวอย่างที่หลายคนที่ได้ศึกษา Flask เฟรมเวิร์คมา โดยจะสังเกตเห็นได้ในโค้ดของ Flask ใน app.py จะมีโค้ดในส่วนของ if __name__ == '__main__': ติดมาด้วย โดยอยู่ในส่วนล่างสุดของไฟล์
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello My First Flask Project"
if __name__ == '__main__':
app.run(debug=True)
สรุปด้านบนแบบรวบรัดกระชับสุด ๆ เลยก็คือถ้าไฟล์ที่กำลังรันอยู่ตอนนี้คือ app.py และไฟล์นี้คือ main ไฟล์ ของเราเพราะว่าไฟล์กำลังถูกรันอยู่นั่นเอง และในฟังก์ชัน app.run() นี้ก็จะมีคำสั่งมากมายที่อยู่ใน Flask เมธอด run ซึ่งจะไว้ใช้รันเซิร์ฟเวอร์, ดีบั๊ก, ฯลฯ
บทความแนะนำสำหรับ Flask
คอร์สเรียนแนะนำสำหรับ Flask
หลังจากอ่านจนจบบทความนี้แล้ว หวังเป็นอย่างยิ่งครับว่าจะทำให้หายข้องใจว่า if __name__ == '__main__' คืออะไร และยังมีเสริมเกี่ยวกับ Module และ Package เข้ามาด้วย เพราะว่าเป็นพื้นฐานก่อนหน้าที่ควรรู้ และขอสรุปไว้ดังนี้ครับ
หากมีข้อสงสัยหรือเสนอแนะเพิ่มเติมก็คอมเมนต์เข้ามาที่คอมเมนต์ด้านล่างได้เลยนะครับ สามารถทำการล็อกอินผ่าน Facebook เพื่อคอมเมนต์และกด response emotions ต่าง ๆ ได้เลยครับ พบกันกับบทความถัดไปครับ See ya next article
| Like | Comment | Share | >> STACKPYTHON
References
The following are really useful resources for making this article happen
[python.org] - Top Level Script Environment
[FreeCodeCamp] - Python if __name__ == __main__ Explained with Code Examples
[https://bic-berkeley.github.io/] - Two double underscores variables
กิจกรรมที่กำลังจะมาถึง
ไม่พลาดกิจกรรมเด็ด ๆ ที่น่าสนใจ
Event นี้จะเริ่มขึ้นใน July 5, 2022
รายละเอียดเพิ่มเติม/สมัครเข้าร่วมโปรคอร์สรวมแรกของปี เรียนไพธอนครบครัน หลากหลาย ลดราคาจาก 7,900฿ เหลือ 6,900฿ พร้อมโบนัส รายละเอีดยเพิ่มเติมในลิงก์ ปล. สมาชิกที่เจอลิงก์นี้จากบทความของเรา แคปภาพมา แอดมินลดให้เพิ่มอีก 200 ครับ