Khi tôi sử dụng shebang #!/usr/bin/env pythonđể chạy tập lệnh, làm thế nào để hệ thống biết pythonnên sử dụng tập lệnh nào ? Nếu tôi tìm một pythonđường dẫn bin trong các biến môi trường, tôi không tìm thấy gì.
env | grep -i python
Khi tôi sử dụng shebang #!/usr/bin/env pythonđể chạy tập lệnh, làm thế nào để hệ thống biết pythonnên sử dụng tập lệnh nào ? Nếu tôi tìm một pythonđường dẫn bin trong các biến môi trường, tôi không tìm thấy gì.
env | grep -i python
Câu trả lời:
Shebang mong muốn một đường dẫn đầy đủ đến trình thông dịch sẽ sử dụng nên cú pháp sau sẽ không chính xác:
#!python
Đặt đường dẫn đầy đủ như thế này có thể hoạt động:
#!/usr/local/bin/python
nhưng sẽ không di động như trăn có thể được cài đặt trong /bin, /opt/python/binhoặc bất cứ nơi nào vị trí khác.
Sử dụng env
#!/usr/bin/env python
là một phương thức cho phép một cách di động để chỉ định cho HĐH một đường dẫn đầy đủ tương đương với đường dẫn pythonđầu tiên được đặt trong PATH.
Dòng shebang (từ bang sharp sharp bang, tức là #!) được xử lý bởi kernel. Nhân không muốn biết về các biến môi trường như PATH. Vì vậy, tên trên dòng shebang phải là một đường dẫn tuyệt đối đến một tệp thực thi. Bạn cũng có thể chỉ định một đối số bổ sung để chuyển đến thực thi đó trước tên tập lệnh (với các hạn chế phụ thuộc hệ thống mà tôi sẽ không đi vào đây). Ví dụ: đối với tập lệnh Python, bạn có thể chỉ định
#!/usr/bin/python
trên dòng đầu tiên và khi bạn thực thi tập lệnh, nhân trên thực tế sẽ thực thi /usr/bin/python /path/to/script. Nhưng điều đó không thuận tiện: bạn cần chỉ định đường dẫn đầy đủ của lệnh. Điều gì nếu bạn có pythontrong /usr/binmột số máy và /usr/local/bintrên những người khác? Hoặc bạn muốn thiết lập của bạn PATHđể /home/joe/opt/python-2.5/binđể sử dụng một phiên bản cụ thể của Python? Vì kernel sẽ không PATHtìm kiếm cho bạn, nên ý tưởng là làm cho kernel chạy một lệnh mà lần lượt tìm kiếm trình thông dịch mong muốn trong PATH:
#!/fixed/path/to/path-lookup-command python
Điều đó path-lookup-commandphải lấy tên của một tệp thực thi làm đối số và tra cứu nó PATHvà thực thi nó: kernel sẽ chạy /fixed/path/to/path-lookup-command python /path/to/script. Khi nó xảy ra, envlệnh làm điều đó. Mục đích chính của nó là để chạy một lệnh với một môi trường khác, nhưng vì nó tìm kiếm tên lệnh trong $PATHđó, nó hoàn hảo cho mục đích của chúng tôi ở đây.
Mặc dù đây không phải là chính thức đảm bảo, hệ thống Unix lịch sử cung cấp envtrong /usr/binvà các hệ thống hiện đại đã giữ vị trí đó một cách chính xác vì việc sử dụng rộng rãi #!/usr/bin/env. Vì vậy, trong thực tế, cách để xác định rằng tập lệnh phải được thực thi bởi trình thông dịch Python yêu thích của người dùng là
#!/usr/bin/env python
envvà which? kể từ đó cũng sẽ có được khả năng thực thi đủ điều kiện nhất từ môi trường PATH của tôi.
whichtìm thấy tệp thực thi và in đường dẫn của nó. envtìm chương trình được chỉ định bởi đối số đầu tiên và thực thi nó, truyền cho nó các đối số còn lại.
envlà một phiên bản eval về whichcơ bản.
Phải, nên chạy:
env | grep PATH
$ PATH của bạn là một danh sách các thư mục. Unix sẽ đi qua danh sách các thư mục đó, theo thứ tự, cho đến khi tìm thấy "python".
Bạn có thể xem thư mục nào nó tìm thấy bằng lệnh 'which':
which python
sys.pathgiữa một env $ env python3 ( ['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/.local/lib/python3.4/site-packages', '/usr/lib/python3.4/site-packages', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']) và ./env/bin/python3 (['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/test/env3/lib/python3.4/site-packages']) được kích hoạt .