__main__.py คืออะไร


326

อะไรคือ__main__.pyไฟล์สำหรับสิ่งที่จัดเรียงของรหัสที่ฉันควรจะใส่ลงในนั้นและเมื่อฉันควรจะมีหนึ่ง?

คำตอบ:


320

บ่อยครั้งโปรแกรม Python จะทำงานโดยการตั้งชื่อไฟล์. py บนบรรทัดคำสั่ง:

$ python my_program.py

นอกจากนี้คุณยังสามารถสร้างไดเรกทอรีหรือ zipfile __main__.pyเต็มรูปแบบของรหัสและรวมถึง จากนั้นคุณสามารถตั้งชื่อไดเรกทอรีหรือ zipfile บนบรรทัดคำสั่งและดำเนินการ__main__.pyโดยอัตโนมัติ:

$ python my_program_dir
$ python my_program.zip
# Or, if the program is accessible as a module
$ python -m my_program

คุณจะต้องตัดสินใจด้วยตัวคุณเองว่าใบสมัครของคุณจะได้รับประโยชน์จากการถูกดำเนินการเช่นนี้หรือไม่


โปรดทราบว่า__main__ โมดูลมักจะไม่ได้มาจาก__main__.pyไฟล์ ทำได้ แต่โดยปกติจะไม่ เมื่อคุณเรียกใช้สคริปต์python my_program.pyสคริปต์จะทำงานเป็น__main__โมดูลแทนmy_programโมดูล สิ่งนี้เกิดขึ้นสำหรับโมดูลที่ทำงานpython -m my_moduleด้วยหรือในหลาย ๆ วิธี

หากคุณเห็นชื่อ__main__ในข้อความแสดงข้อผิดพลาดนั่นไม่ได้แปลว่าคุณควรมองหา__main__.pyไฟล์


22
ฉันพบpython -m program_dirและpython program_dirแตกต่างเล็กน้อย: หลังไม่เคยทำงาน__init__.pyในไดเรกทอรี (ถ้ามี)
brk

5
@brk: ดูเหมือนจะไม่เป็นอย่างนั้นตอนนี้ ฉันก็พยายามและมันวิ่งpython3 program_dir __init__.py
mk12

@ mk12 ฉันลองมันฉันสามารถยืนยันสิ่งที่ค้นพบของ @ brk: python3 dirวิ่ง__main__.pyแต่ไม่ใช่__init__.pyในขณะที่python3 -m dirทำงานทั้งคู่
Marcello Romani

1
@ mk12 อาจเป็นไปได้ว่าคุณมีรหัสอยู่ภายใน__main__.pyซึ่งก่อให้เกิดการนำเข้า__init__.py
วิมาน

100

เป็นสิ่งที่__main__.pyไฟล์หรือไม่?

เมื่อสร้างโมดูล Python เป็นเรื่องปกติที่จะทำให้โมดูลใช้งานบางฟังก์ชั่น (โดยปกติจะมีอยู่ในmainฟังก์ชั่น) เมื่อเรียกใช้เป็นจุดเริ่มต้นของโปรแกรม โดยทั่วไปจะทำด้วยสำนวนทั่วไปต่อไปนี้ซึ่งอยู่ที่ด้านล่างของไฟล์ Python ส่วนใหญ่:

if __name__ == '__main__':
    # execute only if run as the entry point into the program
    main()

__main__.pyคุณจะได้รับความหมายเดียวกันสำหรับแพคเกจหลามกับ นี่เป็นพรอมต์เชลล์ linux $หากคุณไม่มี Bash (หรือ Posix shell) บน Windows เพียงแค่สร้างไฟล์เหล่านี้ที่demo/__<init/main>__.pyกับเนื้อหาในระหว่างEOFs:

$ mkdir demo
$ cat > demo/__init__.py << EOF
print('demo/__init__.py executed')
def main():
    print('main executed')
EOF
$ cat > demo/__main__.py << EOF
print('demo/__main__.py executed')
from __init__ import main
main()
EOF

(ในเชลล์ Posix / Bash คุณสามารถทำข้างต้นโดยไม่มี<< EOFs และลงท้ายด้วยEOFs โดยการป้อนCtrl+ D, อักขระสิ้นสุดไฟล์, ท้ายคำสั่ง cat แต่ละคำสั่ง)

และตอนนี้:

$ python demo
demo/__main__.py executed
demo/__init__.py executed
main executed

คุณสามารถได้มาจากเอกสาร เอกสารพูดว่า:

__main__ - สภาพแวดล้อมสคริปต์ระดับบนสุด

'__main__'เป็นชื่อของขอบเขตที่ใช้รหัสระดับสูง โมดูล__name__ถูกตั้งค่าเท่ากับ'__main__'เมื่ออ่านจากอินพุตมาตรฐานสคริปต์หรือจากพรอมต์แบบโต้ตอบ

โมดูลสามารถค้นพบว่ามันกำลังทำงานอยู่ในขอบเขตหลักหรือไม่โดยการตรวจสอบของมันเอง__name__ซึ่งจะช่วยให้สำนวนสามัญสำหรับการดำเนินการตามเงื่อนไขรหัสในโมดูลเมื่อมันทำงานเป็นสคริปต์หรือด้วยpython -mแต่ไม่เมื่อมันถูกนำเข้า:

if __name__ == '__main__':
      # execute only if run as a script
      main()

สำหรับแพ็กเกจให้ผลเช่นเดียวกันสามารถทำได้โดยการรวมทั้ง โมดูลเนื้อหาที่จะได้รับการดำเนินการเมื่อโมดูลจะทำงานด้วย__main__.py-m

ซิป

คุณสามารถจัดทำแพ็กเกจนี้เป็นไฟล์เดียวและเรียกใช้จากบรรทัดคำสั่งเช่นนี้ - แต่โปรดทราบว่าแพ็กเกจที่บีบอัดแล้วจะไม่สามารถเรียกใช้งานแพ็กเกจย่อยหรือ submodules เป็นจุดเริ่มต้น:

$ python -m zipfile -c demo.zip demo/*
$ python demo.zip
demo/__main__.py executed
demo/__init__.py executed
main() executed

31

__main__.pyใช้สำหรับโปรแกรม python ในไฟล์ zip __main__.pyไฟล์จะถูกดำเนินการเมื่อไฟล์ซิปในการดำเนินการ ตัวอย่างเช่นหากไฟล์ zip เป็นเช่นนี้:

test.zip
     __main__.py

และเนื้อหาของ__main__.pyคือ

import sys
print "hello %s" % sys.argv[1]

ถ้าเราจะวิ่งpython test.zip worldเราจะhello worldออกไป

ดังนั้น__main__.pyไฟล์จะทำงานเมื่อมีการเรียก python ในไฟล์ zip


23

คุณสร้าง__main__.pyขึ้นyourpackageเพื่อให้สามารถเรียกใช้งานได้เป็น:

$ python -m yourpackage

1
-mใช้งานได้หากโปรแกรมสามารถเข้าถึงได้เป็นโมดูลเท่านั้นมิฉะนั้นคุณสามารถใช้python <yourpackage>หมายเหตุ: ไม่มี-mตัวเลือก
Benyamin Jafari

1
@BenyaminJafari มันเป็นไปไม่ได้ที่จะเขียนโปรแกรม Python บรรทัดคำสั่งที่ไม่สามารถเข้าถึงได้เป็นโมดูล บางทีคุณอาจหมายถึงpackage?
Anatoly techtonik

1
เมื่อเราสร้างแพคเกจ Python ซึ่งมี. py หลักเพื่อให้ทำงานpython -m <yourproject>ไม่ทำงาน-mเป็นตัวเลือกที่ซ้ำซ้อน แต่python <yourpackage>ทำงานได้ดี
Benyamin Jafari

@BenyaminJafari ธง -m สร้างความแตกต่างในบางกรณี การดำเนินการจากไดเรกทอรีaและสมมติสคริปต์a/b/c/__main__.py... python -m b.cจะดำเนินการจากไดเรกทอรีและการนำเข้าสคริปต์หลักจะเป็นเมื่อเทียบกับa aแต่python b/cจะดำเนินการจากขอบเขตการนำเข้าของ dir cดังนั้นการนำเข้าใด ๆ ในสคริปต์หลักเช่นimport b.dจะล้มเหลว
MikeCPT

14

หากสคริปต์ของคุณเป็นไดเรกทอรีหรือไฟล์ ZIP แทนที่จะเป็นไฟล์ไพ ธ อนเดียวไฟล์__main__.pyจะถูกดำเนินการเมื่อ "สคริปต์" ถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังตัวแปลภาษาไพ ธ อน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.