ทำไมผู้คนถึงเขียน #! / usr / bin / env python shebang ในบรรทัดแรกของสคริปต์ Python


1046

ดูเหมือนว่าฉันจะเรียกใช้ไฟล์เดียวกันโดยไม่มีบรรทัดนั้น


1
คำตอบด้านล่างที่ระบุว่าเป็นเพียงบรรทัดความคิดเห็น ไม่เป็นเช่นนั้นเสมอไป ฉันมี "สวัสดีโลก!" สคริปต์ CGI (.py) ที่จะทำงานและแสดงหน้าเว็บด้วย#!/usr/bin/env pythonที่ด้านบนสุดเท่านั้น
Chakotay

1
ความเป็นไปได้ที่ซ้ำกันของความแตกต่างระหว่างงูหลามสองตัวคืออะไร
fuad

พวกเขาอาจทำงาน แต่ไม่ได้อยู่ในสภาพแวดล้อมที่ตั้งใจ
นิโคลัสแฮมิลตัน

18
ฉันเคยไปที่โพสต์นี้หลายครั้งใน 7 ปีเพราะบางครั้งฉันลืม env hashbang คัดลอกพาสต้า :)
BugHunterUK

คำตอบ:


1082

หากคุณติดตั้ง Python หลายรุ่น/usr/bin/envจะมั่นใจได้ว่าล่ามที่ใช้นั้นเป็นรุ่นแรกในสภาพแวดล้อมของ$PATHคุณ ทางเลือกอื่นคือการ hardcode บางอย่างเช่น#!/usr/bin/python; ไม่เป็นไร แต่ยืดหยุ่นน้อยกว่า

ใน Unix ไฟล์ที่สามารถเรียกใช้งานได้ซึ่งหมายถึงการตีความสามารถระบุว่าล่ามที่จะใช้โดย#!เริ่มต้นที่บรรทัดแรกแล้วตามด้วยล่าม (และแฟล็กใด ๆ ที่อาจจำเป็นต้องใช้)

หากคุณกำลังพูดถึงแพลตฟอร์มอื่น ๆ กฎนี้ใช้ไม่ได้ (แต่ "shebang line" ไม่เป็นอันตรายและจะช่วยได้ถ้าคุณเคยคัดลอกสคริปต์นั้นไปยังแพลตฟอร์มที่มี Unix base เช่น Linux, Mac ฯลฯ )


267
เพียงเพื่อเพิ่ม: นี้เมื่อคุณทำงานในระบบปฏิบัติการยูนิกซ์โดยทำให้ปฏิบัติการ ( chmod +x myscript.py) แล้วทำงานโดยตรงมากกว่าแค่./myscript.py python myscript.py
Craig McQueen

28
การใช้envให้ความยืดหยุ่นสูงสุดในการที่ผู้ใช้สามารถเลือกล่ามที่จะใช้โดยการเปลี่ยนเส้นทาง บ่อยครั้งที่ความยืดหยุ่นนี้ไม่จำเป็นต้องใช้และข้อเสียคือตัวอย่างของ linux ไม่สามารถใช้ชื่อสคริปต์สำหรับชื่อของกระบวนการในpsและเปลี่ยนกลับเป็น "python" เมื่อบรรจุภัณฑ์ปพลิเคชันสำหรับหลาม distros envตัวอย่างเช่นผมจะแนะนำไม่ให้ใช้
pixelbeat

9
pyตัวเรียกใช้สามารถใช้บรรทัด shebang บน Windows มันรวมอยู่ใน Python 3.3 หรือสามารถติดตั้งได้อย่างอิสระ
jfs

6
คำเตือนที่สำคัญค่า env ในที่สุดก็หมดอายุ ซึ่งไม่น่าจะส่งผลกระทบต่อคุณหากคุณใช้กระบวนการที่มีอายุสั้น อย่างไรก็ตามฉันมีกระบวนการที่กำลังจะตายกับข้อความ/usr/bin/env: Key has expiredหลังจากผ่านไปหลายชั่วโมง
malaverdiere

4
@malaverdiere คุณสามารถลิงก์ไปยังแหล่งข้อมูลใด ๆ ที่อธิบายพฤติกรรมการหมดอายุนี้ได้หรือไม่ ฉันหาพวกมันไม่เจอ
Michael

266

ที่เรียกว่าเส้น shebang ในฐานะที่เป็นรายการวิกิพีเดียอธิบาย :

ในการคำนวณ Shebang (หรือที่เรียกว่า hashbang, hashpling, pound bang หรือ crunchbang) หมายถึงอักขระ "#!" เมื่อพวกเขาเป็นตัวละครสองตัวแรกในคำสั่งล่ามเป็นบรรทัดแรกของไฟล์ข้อความ ในระบบปฏิบัติการที่คล้าย Unix ตัวโหลดโปรแกรมจะใช้อักขระสองตัวนี้เป็นตัวบ่งชี้ว่าไฟล์เป็นสคริปต์และพยายามเรียกใช้สคริปต์นั้นโดยใช้ล่ามที่ระบุโดยส่วนที่เหลือของบรรทัดแรกในไฟล์

ดูที่Unix FAQ entryคำถามที่พบบ่อยเข้า

แม้ใน Windows ที่บรรทัด shebang ไม่ได้กำหนดตัวแปลภาษาที่จะเรียกใช้คุณสามารถส่งตัวเลือกไปยังตัวแปลได้โดยการระบุไว้ในบรรทัด shebang ฉันพบว่ามีประโยชน์ในการเก็บบรรทัด shebang ทั่วไปไว้ในสคริปต์แบบครั้งเดียว (เช่นที่ฉันเขียนเมื่อตอบคำถามใน SO) ดังนั้นฉันจึงสามารถทดสอบพวกเขาได้อย่างรวดเร็วทั้งบน Windows และArchLinux ArchLinux

ยูทิลิตี้ envช่วยให้คุณสามารถเรียกใช้คำสั่งบนเส้นทาง:

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


30
ง่ายต่อการค้นหาด้วย Google - หากมีใครรู้คำหลัก ("shebang line" เป็นสิ่งจำเป็น)
Arafangion

14
จริงๆแล้วคำอธิบายนี้ชัดเจนกว่าข้อมูลอ้างอิงอื่น ๆ ที่ฉันตรวจสอบกับ Google เป็นเรื่องที่ดีกว่าที่จะได้รับการอธิบาย 1 ย่อหน้าโดยตั้งเป้าหมายคำถามแทนที่จะอ่านคู่มือทั้งหมดเพื่อบอกถึงการใช้ที่เป็นไปได้ทั้งหมด
Sam Goldberg

1
@Arafangion คุณอาจพบว่าคำถามนี้มีประโยชน์ TL; DR: symbolhound.com
ulidtko

@ulidtko: เครื่องมือค้นหาที่น่าสนใจลองเขียนคำตอบเพื่อให้คำถามของ john garcias มีคำตอบที่ดีกว่า
Arafangion

1
"แม้แต่บน Windows ซึ่งบรรทัด shebang ไม่ได้กำหนดตัวแปลให้ทำงานคุณสามารถส่งตัวเลือกไปยังตัวแปลได้โดยการระบุไว้ในบรรทัด shebang" นั่นเป็นเพียงแค่ความเท็จ หากสิ่งนั้นเกิดขึ้นนั่นเป็นเพราะล่ามเองกำลังประมวลผลแถวชีแบ หากล่ามไม่ได้รับการยอมรับเป็นพิเศษสำหรับสาย shebang แสดงว่าไม่มีสิ่งใดเกิดขึ้น Windows ไม่ได้ทำอะไรกับเส้น shebang "สิ่งที่คุณอาจจะอธิบายในกรณีนี้คือปล่อยหลาม:. python.org/dev/peps/pep-0397 .
Kaz

154

ขยายคำตอบอื่น ๆ ต่อไปนี้เป็นตัวอย่างเล็กน้อยของวิธีที่สคริปต์บรรทัดคำสั่งของคุณสามารถมีปัญหาโดยการใช้/usr/bin/envบรรทัด Shebang อย่างระมัดระวัง:

$ /usr/local/bin/python -V
Python 2.6.4
$ /usr/bin/python -V
Python 2.5.1
$ cat my_script.py 
#!/usr/bin/env python
import json
print "hello, json"
$ PATH=/usr/local/bin:/usr/bin
$ ./my_script.py 
hello, json
$ PATH=/usr/bin:/usr/local/bin
$ ./my_script.py 
Traceback (most recent call last):
  File "./my_script.py", line 2, in <module>
    import json
ImportError: No module named json

โมดูล json ไม่มีอยู่ใน Python 2.5

วิธีหนึ่งในการป้องกันปัญหาประเภทนั้นคือการใช้ชื่อคำสั่ง python ที่กำหนดเวอร์ชันซึ่งโดยทั่วไปแล้วจะติดตั้งกับ Pythons ส่วนใหญ่:

$ cat my_script.py 
#!/usr/bin/env python2.6
import json
print "hello, json"

หากคุณต้องการแยกความแตกต่างระหว่าง Python 2.x และ Python 3.x รุ่นล่าสุดของ Python 3 ก็มีpython3ชื่อด้วย:

$ cat my_script.py 
#!/usr/bin/env python3
import json
print("hello, json")

27
อืมนั่นไม่ใช่สิ่งที่ฉันได้จากโพสต์นั้น
เกล็นแจ็คแมน

1
ความแตกต่างระหว่างท้องถิ่นและระดับโลก หากwhich pythonส่งคืน/usr/bin/pythonพา ธ ไดเร็กทอรีโลคัลอาจถูกฮาร์ดโค้ด:#!/usr/bin/pythonเป็นเส้นทางไดเรกทอรีท้องถิ่นอาจจะเขียนยาก:แต่นั่นยืดหยุ่นน้อยกว่า#!/usr/bin/env pythonที่มีแอพพลิเคชั่นระดับโลก
noobninja

85

ในการรันสคริปต์ python เราจำเป็นต้องบอกเชลล์สามอย่าง:

  1. ไฟล์นั้นเป็นสคริปต์
  2. นักแปลคนไหนที่เราต้องการเรียกใช้งานสคริปต์
  3. เส้นทางของล่ามดังกล่าว

Shebang #!สำเร็จ (1. ) Shebang เริ่มต้นด้วย#เพราะ#ตัวละครเป็นเครื่องหมายแสดงความคิดเห็นในหลาย ๆ ภาษาสคริปต์ ดังนั้นเนื้อหาของบรรทัด Shebang จึงถูกละเว้นโดยอัตโนมัติ

envสำเร็จคำสั่ง (2) และ (3) หากต้องการอ้างอิง "grawity"

การใช้envคำสั่งทั่วไปคือการเรียกใช้ล่ามโดยการใช้ความจริงที่ env จะค้นหาคำสั่ง $ PATH สำหรับคำสั่งที่บอกให้เรียกใช้ เนื่องจากบรรทัด shebang ต้องมีการระบุเส้นทางแบบสัมบูรณ์และเนื่องจากตำแหน่งของล่ามต่าง ๆ (perl, bash, python) อาจแตกต่างกันมากจึงเป็นเรื่องปกติที่จะใช้:

#!/usr/bin/env perl  แทนที่จะพยายามเดาว่าเป็น / bin / perl, / usr / bin / perl, / usr / local / bin / perl, / usr / local / pkg / perl, / fileserver / usr / bin / perl หรือ / home / MrDaniel / usr / bin / perl บนระบบของผู้ใช้ ...

ในทางตรงกันข้าม env มักจะอยู่ใน / usr / bin / env (ยกเว้นในกรณีที่ไม่มีระบบบางระบบอาจใช้ / bin / env แต่นั่นเป็นโอกาสที่เกิดขึ้นได้ยากและเกิดขึ้นกับระบบที่ไม่ใช่ Linux)


1
"grawity" อยู่ที่ไหน
Pacerier

44

บางทีคำถามของคุณในแง่นี้:

หากคุณต้องการใช้: $python myscript.py

คุณไม่จำเป็นต้องมีบรรทัดนั้นเลย ระบบจะเรียก python และล่าม python จะเรียกใช้สคริปต์ของคุณ

แต่ถ้าคุณตั้งใจจะใช้: $./myscript.py

การเรียกมันโดยตรงเช่นโปรแกรมปกติหรือสคริปต์ทุบตีคุณต้องเขียนบรรทัดนั้นเพื่อระบุระบบที่โปรแกรมใช้เพื่อเรียกใช้ (และทำให้มันทำงานด้วยchmod 755)


หรือคุณสามารถเขียน python3 myscript.py
vijay shanker

44

การexecเรียกระบบของเคอร์เนล Linux เข้าใจ shebangs ( #!) โดยกำเนิด

เมื่อคุณทุบตี:

./something

บน Linux นี้เรียกสายระบบกับเส้นทางexec./something

บรรทัดของเคอร์เนลนี้ถูกเรียกบนไฟล์ที่ส่งไปยังexec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

#!มันอ่านไบต์แรกของไฟล์และเปรียบเทียบพวกเขาไป

หากการเปรียบเทียบเป็นจริงดังนั้นส่วนที่เหลือของบรรทัดจะถูกแยกวิเคราะห์โดยเคอร์เนล Linux ซึ่งทำให้การexecเรียกอีกครั้งด้วยพา ธ/usr/bin/env pythonและไฟล์ปัจจุบันเป็นอาร์กิวเมนต์แรก:

/usr/bin/env python /path/to/script.py

และใช้ได้กับภาษาสคริปต์ที่ใช้ #เป็นอักขระความคิดเห็น

และใช่คุณสามารถสร้างวงวนไม่สิ้นสุดด้วย:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash รู้จักข้อผิดพลาด:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! เพิ่งเกิดขึ้นกับมนุษย์อ่านได้ แต่ไม่จำเป็น

หากไฟล์เริ่มต้นด้วยไบต์ที่แตกต่างกันการexecเรียกของระบบจะใช้ตัวจัดการที่แตกต่างกัน ตัวจัดการในตัวที่สำคัญที่สุดสำหรับไฟล์เรียกทำงานของ ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305ซึ่งจะตรวจสอบไบต์7f 45 4c 46(ซึ่งเกิดขึ้นกับมนุษย์ด้วย) สามารถอ่านได้สำหรับ.ELF) เรามายืนยันว่าโดยการอ่าน 4 ไบต์แรกของ/bin/lsซึ่งเป็นปฏิบัติการ ELF:

head -c 4 "$(which ls)" | hd 

เอาท์พุท:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

ดังนั้นเมื่อเคอร์เนลเห็นไบต์เหล่านั้นจะใช้ไฟล์ ELF วางลงในหน่วยความจำอย่างถูกต้องและเริ่มกระบวนการใหม่ด้วย ดูสิ่งนี้ด้วย:เคอร์เนลรับไฟล์ไบนารีที่ปฏิบัติการได้ซึ่งทำงานภายใต้ linux อย่างไร

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

ฉันไม่คิดว่าPOSIX จะระบุ shebangs อย่างไรก็ตาม: https://unix.stackexchange.com/a/346214/32558ถึงแม้ว่ามันจะกล่าวถึงในส่วนของเหตุผลและในรูปแบบ "ถ้าสคริปต์ที่ปฏิบัติการได้รับการสนับสนุนโดยระบบ เกิดขึ้น" macOS และ FreeBSD ก็ดูเหมือนจะใช้งานได้เช่นกัน

PATH แรงจูงใจในการค้นหา

มีแนวโน้มว่าแรงจูงใจสำคัญอย่างหนึ่งสำหรับการมีอยู่ของ shebangs คือความจริงที่ว่าใน Linux เรามักต้องการเรียกใช้คำสั่งจากPATH:

basename-of-command

แทน:

/full/path/to/basename-of-command

แต่ถ้าไม่มีกลไก shebang แล้ว Linux จะรู้วิธีเปิดไฟล์แต่ละประเภทได้อย่างไร

Hardcoding ส่วนขยายในคำสั่ง:

 basename-of-command.py

หรือการนำการค้นหา PATH ไปใช้กับล่ามทุกตัว:

python basename-of-command

จะเป็นความเป็นไปได้ แต่นี่เป็นปัญหาสำคัญที่ทุกอย่างพังทลายถ้าเราตัดสินใจที่จะเปลี่ยนคำสั่งเป็นภาษาอื่น

Shebangs แก้ปัญหานี้ได้อย่างสวยงาม


39

ในทางเทคนิคใน Python นี่เป็นเพียงบรรทัดความคิดเห็น

บรรทัดนี้ใช้เฉพาะเมื่อคุณเรียกใช้สคริปต์ py จากเชลล์ (จากบรรทัดคำสั่ง) นี่คือสิ่งที่รู้กันว่าเป็น" Shebang !" และมันถูกใช้ในสถานการณ์ต่าง ๆ ไม่ใช่แค่กับสคริปต์ Python

ที่นี่จะสั่งให้เชลล์เริ่มต้นเวอร์ชัน Python ที่เฉพาะเจาะจง (เพื่อดูแลไฟล์ที่เหลือ


Shebang เป็นแนวคิดของ Unix อาจจะมีมูลค่าการกล่าวถึงว่ามันทำงานบน Windows เกินไปถ้าคุณได้ติดตั้งปล่อยงูหลาม py.exeนี่เป็นส่วนหนึ่งของการติดตั้ง Python มาตรฐาน
florisla

38

เหตุผลหลักในการทำเช่นนี้คือการทำให้สคริปต์พกพาข้ามสภาพแวดล้อมระบบปฏิบัติการ

ตัวอย่างเช่นภายใต้ mingw สคริปต์ python ใช้:

#!/c/python3k/python 

และภายใต้การกระจาย GNU / Linux มันเป็นอย่างใดอย่างหนึ่ง:

#!/usr/local/bin/python 

หรือ

#!/usr/bin/python

และภายใต้ระบบ Unix sw / hw เชิงพาณิชย์ที่ดีที่สุดของทุกระบบ (OS / X) มันคือ:

#!/Applications/MacPython 2.5/python

หรือ FreeBSD:

#!/usr/local/bin/python

อย่างไรก็ตามความแตกต่างเหล่านี้สามารถทำให้สคริปต์พกพาได้โดยใช้:

#!/usr/bin/env python

2
ภายใต้ MacOSX /usr/bin/pythonก็ยังเป็น ภายใต้ Linux, Python ที่ติดตั้งโดยระบบนั้นเกือบจะแน่นอน/usr/bin/python(ฉันไม่เคยเห็นอะไรเลยและมันก็ไม่สมเหตุสมผล) /usr/bin/envโปรดทราบว่าอาจจะมีระบบที่ไม่ได้มี
อัลเบิร์ต

1
หากคุณใช้ OSX และใช้ Homebrew และทำตามคำแนะนำการติดตั้งเริ่มต้นมันจะอยู่ภายใต้ #! / usr / local / bin / python
จะ

@ Jean-PaulCalderone: ดูคำตอบของ saaj ด้านล่าง
pydsigner

อัปเดตสำหรับปี 2018: pythonไม่ได้พกพาขนาดนั้นมันคือ Python interpreter Arch Linux มีค่าเริ่มต้นเป็น Python 3 เป็นเวลานานและอาจมีการแจกแจงที่คิดเช่นกันเพราะ Python 2 รองรับจนถึงปี 2020 เท่านั้น
mati865

22

อาจเหมาะสมที่จะเน้นสิ่งหนึ่งที่พลาดมากที่สุดซึ่งอาจขัดขวางความเข้าใจในทันที เมื่อคุณพิมพ์pythonเทอร์มินัลปกติคุณจะไม่ได้ระบุเส้นทางแบบเต็ม แต่ความสามารถในการประมวลผลจะค้นหาในPATHตัวแปรสภาพแวดล้อมแทน ในทางกลับกันเมื่อคุณต้องการรันโปรแกรม Python โดยตรง/path/to/app.pyจะต้องบอกเชลล์ว่าล่ามใช้อะไร (ผ่านhashbangสิ่งที่ผู้ให้ข้อมูลรายอื่นอธิบายไว้ข้างต้น)

Hashbang คาดว่าเส้นทางแบบเต็มไปยังล่าม ดังนั้นเพื่อเรียกใช้โปรแกรมหลามของคุณโดยตรงคุณจะต้องให้เส้นทางที่เต็มไปด้วยงูหลามไบนารีที่แตกต่างกันอย่างมีนัยสำคัญโดยเฉพาะการพิจารณาการใช้virtualenv เพื่อแก้ไขปัญหาการพกพาเคล็ดลับที่/usr/bin/envใช้ เดิมมีวัตถุประสงค์เพื่อเปลี่ยนแปลงสภาพแวดล้อมในสถานที่และเรียกใช้คำสั่งในนั้น เมื่อไม่มีการเปลี่ยนแปลงใด ๆ คำสั่งจะรันคำสั่งในสภาพแวดล้อมปัจจุบันซึ่งจะส่งผลให้การPATHค้นหาเดียวกันซึ่งเป็นการหลอกลวง

แหล่งที่มาจาก unix stackexchange


14

นี่คือการประชุมเชลล์ที่บอกเชลล์ว่าโปรแกรมใดสามารถรันสคริปต์ได้

#! / usr / bin / env python

แก้ไขเส้นทางไปยังไบนารี Python


12

เป็นวิธีที่แนะนำในเอกสารประกอบ:

2.2.2 สคริปต์ Python ที่ทำงานได้

บนระบบ BSD'ish Unix สคริปต์ Python สามารถสร้างได้โดยตรงเช่นเดียวกับเชลล์สคริปต์โดยวางบรรทัด

#! /usr/bin/env python3.2

จากhttp://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts


9

คุณสามารถลองใช้ปัญหานี้โดยใช้ virtualenv

นี่คือ test.py

#! /usr/bin/env python
import sys
print(sys.version)

สร้างสภาพแวดล้อมเสมือนจริง

virtualenv test2.6 -p /usr/bin/python2.6
virtualenv test2.7 -p /usr/bin/python2.7

เปิดใช้งานแต่ละสภาพแวดล้อมจากนั้นตรวจสอบความแตกต่าง

echo $PATH
./test.py

9

เพียงระบุสิ่งที่คุณต้องการใช้ล่าม เพื่อให้เข้าใจสิ่งนี้ให้สร้างไฟล์ผ่านเทอร์มินัลโดยทำtouch test.pyแล้วพิมพ์ไฟล์ดังต่อไปนี้:

#!/usr/bin/env python3
print "test"

และทำchmod +x test.pyเพื่อให้สคริปต์ของคุณทำงานได้ หลังจากนี้เมื่อคุณทำ./test.pyคุณควรได้รับข้อผิดพลาดว่า:

  File "./test.py", line 2
    print "test"
               ^
SyntaxError: Missing parentheses in call to 'print'

เพราะ python3 ไม่สนับสนุนผู้ให้บริการการพิมพ์

ตอนนี้ไปข้างหน้าและเปลี่ยนบรรทัดแรกของรหัสของคุณเป็น:

#!/usr/bin/env python2

และมันจะใช้งานได้พิมพ์testไปยัง stdout เนื่องจาก python2 รองรับผู้ให้บริการการพิมพ์ ดังนั้นตอนนี้คุณได้เรียนรู้วิธีสลับระหว่างตัวแปลสคริปต์


9

ดูเหมือนว่าฉันจะเรียกใช้ไฟล์เดียวกันโดยไม่มีบรรทัดนั้น

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

อย่างไรก็ตามในปี 2011 "Python launcher"ได้รับการพัฒนาซึ่งเลียนแบบพฤติกรรมลีนุกซ์นี้สำหรับ Windows (ในระดับหนึ่ง) สิ่งนี้ จำกัด อยู่เพียงการเลือกตัวแปล Python ที่จะรัน - เช่นเพื่อเลือกระหว่าง Python 2 และ Python 3 บนระบบที่ติดตั้งทั้งคู่ ตัวเรียกใช้งานจะถูกติดตั้งแบบเป็นทางเลือกpy.exeโดยการติดตั้ง Python และสามารถเชื่อมโยงกับ.pyไฟล์เพื่อให้ตัวเรียกใช้นั้นตรวจสอบบรรทัดนั้นและจะเปิดใช้งานตัวแปล Python ที่ระบุ


6
$ python myscript.pyนอกจากนี้เขายังอาจจะใช้
Sinan Marnür

ฉันทำผิดพลาดโดยไม่มีบรรทัดและใช้ python script.py และวันหนึ่งฉันเพิ่งทำ. /myscript.py และทุกอย่างหยุดทำงานจากนั้นการรู้ตัวว่าระบบกำลังมองหาไฟล์เป็นเชลล์สคริปต์แทนที่จะเป็นสคริปต์ไพ ธ อน
Guagua

8

นี่เป็นข้อมูลทางประวัติศาสตร์มากกว่าคำตอบ "จริง"

โปรดจำไว้ว่าในวันที่คุณมียูนิกซ์จำนวนมากเช่นระบบปฏิบัติการซึ่งนักออกแบบทุกคนมีความคิดของตัวเองว่าจะใส่อะไรไว้ที่ไหนและบางครั้งก็ไม่รวมถึง Python, Perl, Bash หรือ GNU / Open Source อื่น ๆ อีกมากมายเลย .

นี่เป็นเรื่องจริงของการแจกแจงลินุกซ์ที่แตกต่างกัน บน Linux - pre-FHS [1] - คุณอาจมี python ใน / usr / bin / หรือ / usr / local / bin / หรืออาจไม่มีการติดตั้งดังนั้นคุณจึงสร้างของคุณเองและใส่ไว้ใน ~ / bin

Solaris เป็นสิ่งที่แย่ที่สุดที่ฉันเคยทำส่วนหนึ่งมาจากการเปลี่ยนจาก Berkeley Unix เป็น System V คุณสามารถปิดท้ายด้วยสิ่งต่างๆใน / usr /, / usr / local /, / usr / ucb, / opt / ฯลฯ สำหรับเส้นทางที่ยาวจริงๆ ฉันมีความทรงจำเกี่ยวกับสิ่งต่าง ๆ จาก Sunfreeware.com ที่ติดตั้งแต่ละแพ็คเกจในไดเรกทอรีของตัวเอง แต่ฉันจำไม่ได้ว่ามันเชื่อมโยงไบนารีเข้ากับ / usr / bin หรือไม่

โอ้และบางครั้ง / usr / bin อยู่บนเซิร์ฟเวอร์ NFS [2]

ดังนั้นenvยูทิลิตี้นี้จึงได้รับการพัฒนาเพื่อแก้ไขปัญหานี้

จากนั้นคุณสามารถเขียน#!/bin/env interpreterและตราบใดที่เส้นทางเป็นสิ่งที่เหมาะสมมีโอกาสที่เหมาะสมในการทำงาน แน่นอนความหมายที่สมเหตุสมผล (สำหรับ Python และ Perl) ที่คุณได้ตั้งค่าตัวแปรสภาพแวดล้อมที่เหมาะสม สำหรับ bash / ksh / zsh มันใช้งานได้

นี่เป็นเรื่องสำคัญเพราะผู้คนกำลังอ่านสคริปต์เชลล์ (เช่น perl และ python) และถ้าคุณเขียนโค้ด / usr / bin / python ลงบนเวิร์กสเตชัน Red Hat Linux ของคุณมันจะทำให้ SGI แย่ลง ... ฉันคิดว่า IRIX ใส่หลามในจุดที่ถูกต้อง แต่ในสถานี Sparc มันอาจไม่ทำงานเลย

ฉันคิดถึงสถานี Sparc ของฉัน แต่ไม่มาก ตกลงตอนนี้คุณมีฉันหมุนรอบใน E-Bay Bastages

[1] มาตรฐานลำดับชั้นของระบบไฟล์ https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

[2] ใช่และบางครั้งผู้คนก็ยังทำสิ่งนี้อยู่ และไม่ฉันไม่ได้สวมหัวผักกาดหรือหัวหอมบนสายพานของฉัน


5

หากคุณกำลังเรียกใช้สคริปต์ของคุณในสภาพแวดล้อมเสมือนพูดvenvจากนั้นดำเนินการwhich pythonในขณะที่ทำงานvenvจะแสดงเส้นทางไปยังล่าม Python:

~/Envs/venv/bin/python

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

  • หากคุณอัปโหลดสคริปต์เพื่อให้พื้นที่เก็บข้อมูลที่คุณกำลังบังคับให้ผู้ใช้อื่น ๆ ที่มีชื่อสภาพแวดล้อมเสมือนเดียวกัน นี่คือถ้าพวกเขาระบุปัญหาก่อน
  • คุณจะไม่สามารถเรียกใช้สคริปต์ในสภาพแวดล้อมเสมือนจริงหลาย ๆแม้ว่าคุณมีแพคเกจที่จำเป็นทั้งหมดในสภาพแวดล้อมเสมือนจริงอื่น ๆ

ดังนั้นเพื่อเพิ่มคำตอบของโจนาธาน shebang ในอุดมคตินั้น#!/usr/bin/env pythonไม่เพียง แต่สำหรับการพกพาข้ามระบบปฏิบัติการ แต่สำหรับการพกพาข้ามสภาพแวดล้อมเสมือนจริงเช่นกัน!


3

เมื่อพิจารณาถึงปัญหาการพกพาระหว่างpython2และpython3คุณควรระบุเวอร์ชันใดเวอร์ชันหนึ่งเสมอเว้นแต่ว่าโปรแกรมของคุณเข้ากันได้กับทั้งคู่

การกระจายการจัดส่งสินค้าบางอย่างจะpythonsymlinked ไปpython3ในขณะที่ตอนนี้ - ไม่ต้องพึ่งพาpythonความเป็นอยู่python2ความเป็นอยู่

สิ่งนี้เน้นโดยPEP 394 :

เพื่อให้สามารถยอมรับความแตกต่างระหว่างแพลตฟอร์มได้รหัสใหม่ทั้งหมดที่จำเป็นต้องเรียกใช้ Python interpreter ไม่ควรระบุ python แต่ควรระบุ python2 หรือ python3 อย่างใดอย่างหนึ่ง (หรือ python2.x และ python3.x รุ่นที่เฉพาะเจาะจงมากขึ้นโปรดดูMigration Notes ) . ความแตกต่างนี้ควรทำในรูปแบบ shebang เมื่อเรียกใช้จากเชลล์สคริปต์เมื่อเรียกใช้ผ่านการเรียกของระบบ () หรือเมื่อเรียกใช้ในบริบทอื่น


2

มันบอกล่ามไพ ธ อนรุ่นใดที่จะรันโปรแกรมด้วยเมื่อคุณมีไพ ธ อนหลายรุ่น


0

อนุญาตให้คุณเลือกไฟล์ที่คุณต้องการใช้ ซึ่งมีประโยชน์มากถ้าคุณอาจติดตั้งหลามหลายตัวและโมดูลที่แตกต่างกันในแต่ละอันและต้องการเลือก เช่น

#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    echo Using preferred python $ALTERNATIVE_PYTHON
    exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())

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