Tôi có một kịch bản Python cần được chạy với một cài đặt python cụ thể. Có cách nào để tạo ra một shebang để nó chạy với $FOO/bar/MyCustomPython
không?
Tôi có một kịch bản Python cần được chạy với một cài đặt python cụ thể. Có cách nào để tạo ra một shebang để nó chạy với $FOO/bar/MyCustomPython
không?
Câu trả lời:
Dòng shebang rất hạn chế. Trong nhiều biến thể unix (bao gồm cả Linux), bạn chỉ có thể có hai từ: một lệnh và một đối số duy nhất. Cũng thường có một giới hạn chiều dài.
Giải pháp chung là viết một trình bao bọc vỏ nhỏ. Đặt tên cho tập lệnh Python foo.py
và đặt tập lệnh shell bên cạnh foo.py
và gọi nó foo
. Cách tiếp cận này không yêu cầu bất kỳ tiêu đề cụ thể nào trên tập lệnh Python.
#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"
Một cách tiếp cận hấp dẫn khác là viết một tập lệnh bao bọc như ở trên và đặt #!/path/to/wrapper/script
làm dòng shebang trên tập lệnh Python. Tuy nhiên, hầu hết các đơn vị không hỗ trợ xâu chuỗi các kịch bản shebang, vì vậy điều này sẽ không hoạt động.
Nếu MyCustomPython
là trong $PATH
, bạn có thể sử dụng env
để tìm kiếm nó:
#!/usr/bin/env MyCustomPython
import …
Tuy nhiên, một cách tiếp cận khác là sắp xếp cho tập lệnh vừa là tập lệnh shell hợp lệ (vừa tự tải trình thông dịch Python đúng) và tập lệnh hợp lệ trong ngôn ngữ đích (ở đây là Python). Điều này đòi hỏi bạn phải tìm cách viết một tập lệnh ngôn ngữ kép như vậy cho ngôn ngữ mục tiêu của bạn. Trong Perl, điều này được gọi là if $running_under_some_shell
.
#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
if $running_under_some_shell;
use …
Đây là một cách để đạt được hiệu ứng tương tự trong Python. Trong shell, "true"
là true
tiện ích, bỏ qua các đối số của nó (hai chuỗi ký tự đơn :
và '
) và trả về một giá trị thực. Trong Python, "true"
là một chuỗi đúng khi được hiểu là boolean, vì vậy đây là một if
lệnh luôn luôn đúng và thực thi một chuỗi ký tự.
#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …
Mã Rosetta có các tập lệnh ngôn ngữ kép như vậy trong một số ngôn ngữ khác.
PYTHONPATH
biến env để tải các mô-đun từ một vị trí không chuẩn cho tập lệnh CGI trên hệ thống mà tôi không có quyền truy cập root. Cứu người. Cảm ơn một lần nữa.
Các dòng Shebang không trải qua quá trình mở rộng biến đổi, vì vậy bạn không thể sử dụng $FOO/MyCustomPython
vì nó sẽ tìm kiếm một tên thực thi có tên là Dollar-FOO -...
Một cách khác là để shebang của bạn trỏ đến tập lệnh shell làm trình thông dịch và tập lệnh shell này sau đó có thể sử dụng các biến môi trường để xác định vị trí chính xác và thực thi nó.
Ví dụ: tạo mypython.sh
tập lệnh trong /usr/local/bin
(hoặc bất kỳ thư mục nào khác trên của bạn $PATH
), với nội dung sau:
#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"
sau đó bạn có thể sử dụng dòng shebang này để thực thi tập lệnh Python thông MyCustomPython
qua mypython.sh
:
#!/usr/bin/env mypython.sh
$python
, không phải $PYTHON
- theo quy ước, chúng tôi viết hoa các biến môi trường (PAGER, EDITOR, SHELL ... $PYTHON
trong tập lệnh của bạn không phải là biến môi trường) và các biến shell nội bộ (BASH_VERSION, RANDOM, ...). Tất cả các tên biến khác phải chứa ít nhất một chữ cái viết thường. Quy ước này tránh vô tình ghi đè các biến môi trường và nội bộ. Ngoài ra, không sử dụng tiện ích mở rộng cho tập lệnh của bạn. Các tập lệnh xác định các lệnh mới mà bạn có thể chạy và các lệnh thường không được cung cấp các tiện ích mở rộng.
Bạn có thể sử dụng đường dẫn tuyệt đối để cài đặt python tùy chỉnh hoặc bạn có thể đặt nó vào $PATH
và sử dụng #!/usr/bin/env [command]
. Mặt khác, viết một trình bao bọc cho nó và sử dụng exec
để thay thế hình ảnh quá trình, như một ví dụ:
#!/bin/bash
exec "$ENV/python" "$@"
Trước tiên, hãy xác định phiên bản Python của bạn khác với Python chuẩn đã được cài đặt như thế nào (ví dụ: một mô-đun bổ sung) và sau đó khi bắt đầu chương trình 'chuyển đổi' cách Python được gọi:
#!/usr/bin/python
import os
import sys
try:
import MyCustomModule
except ImportError:
# only need to use expandvar if you know the string below has an envvar
custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
os.execv(custprog, sys.argv) # call alternate python with the same arguments
raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter
Điều này sẽ cho phép chương trình được gọi bởi bất kỳ phiên bản Python nào khác. Tôi làm một cái gì đó tương tự với một ví dụ với thư viện sql tích hợp không thể được nhập dưới dạng một mô-đun trong python của hệ thống.
Nếu bạn có thể thay thế $FOO
trong $FOO/bar/MyCustomPython
với các tùy chọn con đường bê tông, bạn có thể nói với các env
dòng công việc nơi để tìm kiếm phiên bản Python tùy chỉnh của bạn bằng cách trực tiếp thiết lập một tùy chỉnh PATH
trong đó.
#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python
Chỉnh sửa : Có vẻ như chỉ hoạt động mà không có dấu ngoặc kép xung quanh việc gán giá trị PATH:
#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
PATH
như thế này:PATH=$PATH:/path/to/whatever...