ดูเหมือนว่าฉันจะเรียกใช้ไฟล์เดียวกันโดยไม่มีบรรทัดนั้น
ดูเหมือนว่าฉันจะเรียกใช้ไฟล์เดียวกันโดยไม่มีบรรทัดนั้น
คำตอบ:
หากคุณติดตั้ง Python หลายรุ่น/usr/bin/env
จะมั่นใจได้ว่าล่ามที่ใช้นั้นเป็นรุ่นแรกในสภาพแวดล้อมของ$PATH
คุณ ทางเลือกอื่นคือการ hardcode บางอย่างเช่น#!/usr/bin/python
; ไม่เป็นไร แต่ยืดหยุ่นน้อยกว่า
ใน Unix ไฟล์ที่สามารถเรียกใช้งานได้ซึ่งหมายถึงการตีความสามารถระบุว่าล่ามที่จะใช้โดย#!
เริ่มต้นที่บรรทัดแรกแล้วตามด้วยล่าม (และแฟล็กใด ๆ ที่อาจจำเป็นต้องใช้)
หากคุณกำลังพูดถึงแพลตฟอร์มอื่น ๆ กฎนี้ใช้ไม่ได้ (แต่ "shebang line" ไม่เป็นอันตรายและจะช่วยได้ถ้าคุณเคยคัดลอกสคริปต์นั้นไปยังแพลตฟอร์มที่มี Unix base เช่น Linux, Mac ฯลฯ )
chmod +x myscript.py
) แล้วทำงานโดยตรงมากกว่าแค่./myscript.py
python myscript.py
env
ให้ความยืดหยุ่นสูงสุดในการที่ผู้ใช้สามารถเลือกล่ามที่จะใช้โดยการเปลี่ยนเส้นทาง บ่อยครั้งที่ความยืดหยุ่นนี้ไม่จำเป็นต้องใช้และข้อเสียคือตัวอย่างของ linux ไม่สามารถใช้ชื่อสคริปต์สำหรับชื่อของกระบวนการในps
และเปลี่ยนกลับเป็น "python" เมื่อบรรจุภัณฑ์ปพลิเคชันสำหรับหลาม distros env
ตัวอย่างเช่นผมจะแนะนำไม่ให้ใช้
py
ตัวเรียกใช้สามารถใช้บรรทัด shebang บน Windows มันรวมอยู่ใน Python 3.3 หรือสามารถติดตั้งได้อย่างอิสระ
/usr/bin/env: Key has expired
หลังจากผ่านไปหลายชั่วโมง
ที่เรียกว่าเส้น shebang ในฐานะที่เป็นรายการวิกิพีเดียอธิบาย :
ในการคำนวณ Shebang (หรือที่เรียกว่า hashbang, hashpling, pound bang หรือ crunchbang) หมายถึงอักขระ "#!" เมื่อพวกเขาเป็นตัวละครสองตัวแรกในคำสั่งล่ามเป็นบรรทัดแรกของไฟล์ข้อความ ในระบบปฏิบัติการที่คล้าย Unix ตัวโหลดโปรแกรมจะใช้อักขระสองตัวนี้เป็นตัวบ่งชี้ว่าไฟล์เป็นสคริปต์และพยายามเรียกใช้สคริปต์นั้นโดยใช้ล่ามที่ระบุโดยส่วนที่เหลือของบรรทัดแรกในไฟล์
ดูที่Unix FAQ entryคำถามที่พบบ่อยเข้า
แม้ใน Windows ที่บรรทัด shebang ไม่ได้กำหนดตัวแปลภาษาที่จะเรียกใช้คุณสามารถส่งตัวเลือกไปยังตัวแปลได้โดยการระบุไว้ในบรรทัด shebang ฉันพบว่ามีประโยชน์ในการเก็บบรรทัด shebang ทั่วไปไว้ในสคริปต์แบบครั้งเดียว (เช่นที่ฉันเขียนเมื่อตอบคำถามใน SO) ดังนั้นฉันจึงสามารถทดสอบพวกเขาได้อย่างรวดเร็วทั้งบน Windows และArchLinux ArchLinux
ยูทิลิตี้ envช่วยให้คุณสามารถเรียกใช้คำสั่งบนเส้นทาง:
อาร์กิวเมนต์แรกที่เหลือจะระบุชื่อโปรแกรมที่จะเรียกใช้ มันถูกค้นหาตาม
PATH
ตัวแปรสภาพแวดล้อม อาร์กิวเมนต์ที่เหลืออยู่จะถูกส่งเป็นอาร์กิวเมนต์ไปยังโปรแกรมนั้น
ขยายคำตอบอื่น ๆ ต่อไปนี้เป็นตัวอย่างเล็กน้อยของวิธีที่สคริปต์บรรทัดคำสั่งของคุณสามารถมีปัญหาโดยการใช้/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")
which python
ส่งคืน/usr/bin/python
พา ธ ไดเร็กทอรีโลคัลอาจถูกฮาร์ดโค้ด:#!/usr/bin/python
เป็นเส้นทางไดเรกทอรีท้องถิ่นอาจจะเขียนยาก:แต่นั่นยืดหยุ่นน้อยกว่า#!/usr/bin/env python
ที่มีแอพพลิเคชั่นระดับโลก
ในการรันสคริปต์ python เราจำเป็นต้องบอกเชลล์สามอย่าง:
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)
บางทีคำถามของคุณในแง่นี้:
หากคุณต้องการใช้: $python myscript.py
คุณไม่จำเป็นต้องมีบรรทัดนั้นเลย ระบบจะเรียก python และล่าม python จะเรียกใช้สคริปต์ของคุณ
แต่ถ้าคุณตั้งใจจะใช้: $./myscript.py
การเรียกมันโดยตรงเช่นโปรแกรมปกติหรือสคริปต์ทุบตีคุณต้องเขียนบรรทัดนั้นเพื่อระบุระบบที่โปรแกรมใช้เพื่อเรียกใช้ (และทำให้มันทำงานด้วยchmod 755
)
การ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 แก้ปัญหานี้ได้อย่างสวยงาม
ในทางเทคนิคใน Python นี่เป็นเพียงบรรทัดความคิดเห็น
บรรทัดนี้ใช้เฉพาะเมื่อคุณเรียกใช้สคริปต์ py จากเชลล์ (จากบรรทัดคำสั่ง) นี่คือสิ่งที่รู้กันว่าเป็น" Shebang !" และมันถูกใช้ในสถานการณ์ต่าง ๆ ไม่ใช่แค่กับสคริปต์ Python
ที่นี่จะสั่งให้เชลล์เริ่มต้นเวอร์ชัน Python ที่เฉพาะเจาะจง (เพื่อดูแลไฟล์ที่เหลือ
py.exe
นี่เป็นส่วนหนึ่งของการติดตั้ง Python มาตรฐาน
เหตุผลหลักในการทำเช่นนี้คือการทำให้สคริปต์พกพาข้ามสภาพแวดล้อมระบบปฏิบัติการ
ตัวอย่างเช่นภายใต้ 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
/usr/bin/python
ก็ยังเป็น ภายใต้ Linux, Python ที่ติดตั้งโดยระบบนั้นเกือบจะแน่นอน/usr/bin/python
(ฉันไม่เคยเห็นอะไรเลยและมันก็ไม่สมเหตุสมผล) /usr/bin/env
โปรดทราบว่าอาจจะมีระบบที่ไม่ได้มี
python
ไม่ได้พกพาขนาดนั้นมันคือ Python interpreter Arch Linux มีค่าเริ่มต้นเป็น Python 3 เป็นเวลานานและอาจมีการแจกแจงที่คิดเช่นกันเพราะ Python 2 รองรับจนถึงปี 2020 เท่านั้น
อาจเหมาะสมที่จะเน้นสิ่งหนึ่งที่พลาดมากที่สุดซึ่งอาจขัดขวางความเข้าใจในทันที เมื่อคุณพิมพ์python
เทอร์มินัลปกติคุณจะไม่ได้ระบุเส้นทางแบบเต็ม แต่ความสามารถในการประมวลผลจะค้นหาในPATH
ตัวแปรสภาพแวดล้อมแทน ในทางกลับกันเมื่อคุณต้องการรันโปรแกรม Python โดยตรง/path/to/app.py
จะต้องบอกเชลล์ว่าล่ามใช้อะไร (ผ่านhashbangสิ่งที่ผู้ให้ข้อมูลรายอื่นอธิบายไว้ข้างต้น)
Hashbang คาดว่าเส้นทางแบบเต็มไปยังล่าม ดังนั้นเพื่อเรียกใช้โปรแกรมหลามของคุณโดยตรงคุณจะต้องให้เส้นทางที่เต็มไปด้วยงูหลามไบนารีที่แตกต่างกันอย่างมีนัยสำคัญโดยเฉพาะการพิจารณาการใช้virtualenv เพื่อแก้ไขปัญหาการพกพาเคล็ดลับที่/usr/bin/env
ใช้ เดิมมีวัตถุประสงค์เพื่อเปลี่ยนแปลงสภาพแวดล้อมในสถานที่และเรียกใช้คำสั่งในนั้น เมื่อไม่มีการเปลี่ยนแปลงใด ๆ คำสั่งจะรันคำสั่งในสภาพแวดล้อมปัจจุบันซึ่งจะส่งผลให้การPATH
ค้นหาเดียวกันซึ่งเป็นการหลอกลวง
นี่คือการประชุมเชลล์ที่บอกเชลล์ว่าโปรแกรมใดสามารถรันสคริปต์ได้
#! / usr / bin / env python
แก้ไขเส้นทางไปยังไบนารี Python
เป็นวิธีที่แนะนำในเอกสารประกอบ:
2.2.2 สคริปต์ Python ที่ทำงานได้
บนระบบ BSD'ish Unix สคริปต์ Python สามารถสร้างได้โดยตรงเช่นเดียวกับเชลล์สคริปต์โดยวางบรรทัด
#! /usr/bin/env python3.2
จากhttp://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
คุณสามารถลองใช้ปัญหานี้โดยใช้ 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
เพียงระบุสิ่งที่คุณต้องการใช้ล่าม เพื่อให้เข้าใจสิ่งนี้ให้สร้างไฟล์ผ่านเทอร์มินัลโดยทำ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 รองรับผู้ให้บริการการพิมพ์ ดังนั้นตอนนี้คุณได้เรียนรู้วิธีสลับระหว่างตัวแปลสคริปต์
ดูเหมือนว่าฉันจะเรียกใช้ไฟล์เดียวกันโดยไม่มีบรรทัดนั้น
ถ้าเป็นเช่นนั้นบางทีคุณกำลังใช้งานโปรแกรม Python บน Windows? Windows ไม่ได้ใช้บรรทัดนั้น แต่จะใช้นามสกุลไฟล์เพื่อเรียกใช้โปรแกรมที่เกี่ยวข้องกับนามสกุลไฟล์
อย่างไรก็ตามในปี 2011 "Python launcher"ได้รับการพัฒนาซึ่งเลียนแบบพฤติกรรมลีนุกซ์นี้สำหรับ Windows (ในระดับหนึ่ง) สิ่งนี้ จำกัด อยู่เพียงการเลือกตัวแปล Python ที่จะรัน - เช่นเพื่อเลือกระหว่าง Python 2 และ Python 3 บนระบบที่ติดตั้งทั้งคู่ ตัวเรียกใช้งานจะถูกติดตั้งแบบเป็นทางเลือกpy.exe
โดยการติดตั้ง Python และสามารถเชื่อมโยงกับ.py
ไฟล์เพื่อให้ตัวเรียกใช้นั้นตรวจสอบบรรทัดนั้นและจะเปิดใช้งานตัวแปล Python ที่ระบุ
$ python myscript.py
นอกจากนี้เขายังอาจจะใช้
นี่เป็นข้อมูลทางประวัติศาสตร์มากกว่าคำตอบ "จริง"
โปรดจำไว้ว่าในวันที่คุณมียูนิกซ์จำนวนมากเช่นระบบปฏิบัติการซึ่งนักออกแบบทุกคนมีความคิดของตัวเองว่าจะใส่อะไรไว้ที่ไหนและบางครั้งก็ไม่รวมถึง 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] ใช่และบางครั้งผู้คนก็ยังทำสิ่งนี้อยู่ และไม่ฉันไม่ได้สวมหัวผักกาดหรือหัวหอมบนสายพานของฉัน
หากคุณกำลังเรียกใช้สคริปต์ของคุณในสภาพแวดล้อมเสมือนพูดvenv
จากนั้นดำเนินการwhich python
ในขณะที่ทำงานvenv
จะแสดงเส้นทางไปยังล่าม Python:
~/Envs/venv/bin/python
โปรดทราบว่าชื่อของสภาพแวดล้อมเสมือนถูกฝังอยู่ในเส้นทางไปยังล่าม Python ดังนั้นการเข้ารหัสฮาร์ดไดร์ฟนี้ในสคริปต์ของคุณจะทำให้เกิดปัญหาสองประการ:
ดังนั้นเพื่อเพิ่มคำตอบของโจนาธาน shebang ในอุดมคตินั้น#!/usr/bin/env python
ไม่เพียง แต่สำหรับการพกพาข้ามระบบปฏิบัติการ แต่สำหรับการพกพาข้ามสภาพแวดล้อมเสมือนจริงเช่นกัน!
เมื่อพิจารณาถึงปัญหาการพกพาระหว่างpython2
และpython3
คุณควรระบุเวอร์ชันใดเวอร์ชันหนึ่งเสมอเว้นแต่ว่าโปรแกรมของคุณเข้ากันได้กับทั้งคู่
การกระจายการจัดส่งสินค้าบางอย่างจะpython
symlinked ไปpython3
ในขณะที่ตอนนี้ - ไม่ต้องพึ่งพาpython
ความเป็นอยู่python2
ความเป็นอยู่
สิ่งนี้เน้นโดยPEP 394 :
เพื่อให้สามารถยอมรับความแตกต่างระหว่างแพลตฟอร์มได้รหัสใหม่ทั้งหมดที่จำเป็นต้องเรียกใช้ Python interpreter ไม่ควรระบุ python แต่ควรระบุ python2 หรือ python3 อย่างใดอย่างหนึ่ง (หรือ python2.x และ python3.x รุ่นที่เฉพาะเจาะจงมากขึ้นโปรดดูMigration Notes ) . ความแตกต่างนี้ควรทำในรูปแบบ shebang เมื่อเรียกใช้จากเชลล์สคริปต์เมื่อเรียกใช้ผ่านการเรียกของระบบ () หรือเมื่อเรียกใช้ในบริบทอื่น
มันบอกล่ามไพ ธ อนรุ่นใดที่จะรันโปรแกรมด้วยเมื่อคุณมีไพ ธ อนหลายรุ่น
อนุญาตให้คุณเลือกไฟล์ที่คุณต้องการใช้ ซึ่งมีประโยชน์มากถ้าคุณอาจติดตั้งหลามหลายตัวและโมดูลที่แตกต่างกันในแต่ละอันและต้องการเลือก เช่น
#!/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())
สิ่งนี้บอกสคริปต์ว่าเป็นไดเรกทอรี python ที่ไหน!
#! /usr/bin/env python
#!/usr/bin/env python
ที่ด้านบนสุดเท่านั้น