그 줄없이 파일이 동일하게 실행되는 것처럼 보입니다.
그 줄없이 파일이 동일하게 실행되는 것처럼 보입니다.
답변:
여러 버전의 Python이 설치되어 있으면 /usr/bin/env
사용되는 인터프리터가 환경의 첫 번째 인터프리터인지 확인하십시오 $PATH
. 대안은 다음과 같은 것을 하드 코딩하는 것입니다 #!/usr/bin/python
. 괜찮지 만 유연성은 떨어집니다.
유닉스에서, 해석 되는 실행 파일 #!
은 첫 줄의 시작 부분에 인터프리터 (및 필요한 플래그)를 붙여서 어떤 인터프리터를 사용해야하는지 나타낼 수 있습니다 .
당신이 다른 플랫폼에 대해 얘기하는 경우, 물론,이 규칙이 적용되지 않습니다 (하지만 "오두막 라인은"아무런 해를 끼치 지 않으며, 혹시 플랫폼에 해당 스크립트를 복사하면 도움이 될 것입니다 와 같은 리눅스, 맥 등의 유닉스 기반, 등).
chmod +x myscript.py
) 직접 실행하는 ./myscript.py
것보다는 을 실행할 때 적용됩니다 python myscript.py
.
env
하면 사용자가 PATH를 변경하여 사용할 인터프리터를 선택할 수있는 유연성이 극대화됩니다. 종종 이러한 유연성이 필요하지는 않지만 단점은 리눅스가 프로세스 이름에 스크립트 이름을 사용할 수없고 ps
"python"으로 되돌아 간다는 것입니다. 예를 들어 배포판 용 파이썬 앱을 패키징 할 때는 사용하지 않는 것이 좋습니다 env
.
py
런처 는 Windows에서 shebang 라인을 사용할 수 있습니다. 파이썬 3.3에 포함되어 있거나 독립적으로 설치할 수 있습니다 .
/usr/bin/env: Key has expired
몇 시간 후에 메시지로 프로세스가 죽었습니다 .
이것을 세방 라인 이라고합니다 . 현상태대로 위키 백과 항목을 설명합니다 :
컴퓨팅에서 shebang (해시 뱅, hashpling, pound bang 또는 crunchbang이라고도 함)은 "#!"문자를 나타냅니다. 텍스트 파일의 첫 번째 행으로 인터프리터 지시문에서 처음 두 문자 인 경우 유닉스 계열 운영 체제에서 프로그램 로더는 파일이 스크립트임을 나타내는 표시로이 두 문자가 존재하고 파일의 첫 번째 행에 지정된 인터프리터를 사용하여 해당 스크립트를 실행하려고합니다.
유닉스 FAQ 항목 도 참조하십시오 .
shebang 행이 인터프리터를 실행할 것으로 판별하지 않는 Windows에서도 shebang 행에 옵션을 지정하여 인터프리터에 옵션을 전달할 수 있습니다. 일회성 스크립트 (예 : 질문에 대답 할 때 쓰는 스크립트)에 일반 shebang 줄을 유지하는 것이 유용하므로 Windows 및 ArchLinux 모두에서 빠르게 테스트 할 수 있습니다 .
ENV 유틸리티를 사용하면 경로에 명령을 호출 할 수 있습니다 :
첫 번째 나머지 인수는 호출 할 프로그램 이름을 지정합니다.
PATH
환경 변수 에 따라 검색됩니다 . 나머지 인수는 해당 프로그램에 인수로 전달됩니다.
다른 답변을 조금 확장하면 다음과 같이 /usr/bin/env
셰방 라인 을 신중하게 사용하여 명령 줄 스크립트가 어떻게 문제를 일으킬 수 있는지에 대한 작은 예가 있습니다 .
$ /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과 함께 설치되는 버전이 지정된 python 명령 이름을 사용하는 것입니다.
$ 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
글로벌 응용 프로그램 보다 유연성이 떨어 집니다.
파이썬 스크립트를 실행하려면 쉘에 세 가지를 알려야합니다.
shebang은 #!
달성합니다 (1.). 문자는 많은 스크립팅 언어에서 주석 마커 #
이기 때문에 shebang은로 시작 #
합니다. 따라서 shebang 행의 내용은 인터프리터에 의해 자동으로 무시됩니다.
이 env
명령은 (2.)와 (3.)을 달성합니다. "창의력"을 인용하면
이
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
그 줄은 전혀 필요하지 않습니다. 시스템은 파이썬을 호출하고 파이썬 인터프리터는 스크립트를 실행합니다.
그러나 사용하려는 경우 : $./myscript.py
일반 프로그램이나 bash 스크립트처럼 직접 호출하면 해당 라인을 작성하여 프로그램을 실행하는 데 사용하는 시스템에 지정하고 (와 함께 실행 가능하게 함 chmod 755
)
exec
Linux 커널 의 시스템 호출은 #!
기본적으로 shebang을 이해합니다 ( )
bash에서 할 때 :
./something
Linux에서는 exec
경로를 사용 하여 시스템 호출을 호출합니다 ./something
.
이 커널 라인은 https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25에 전달 된 파일에서 호출됩니다 exec
.
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: /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
). /bin/ls
ELF 실행 파일 인의 첫 번째 4 바이트를 읽음으로써 확인하십시오 .
head -c 4 "$(which ls)" | hd
산출:
00000000 7f 45 4c 46 |.ELF|
00000004
따라서 커널이 해당 바이트를 볼 때 ELF 파일을 가져 와서 메모리에 올바르게 넣고 새 프로세스를 시작합니다. 또한 커널은 리눅스에서 실행 가능한 실행 바이너리 파일을 어떻게 얻습니까?
마지막으로, binfmt_misc
메커니즘을 사용하여 자체 Shebang 처리기를 추가 할 수 있습니다 . 예를 들어, 파일에 대한 사용자 정의 핸들러를.jar
추가 할 수 있습니다 . 이 메커니즘은 파일 확장자 별 핸들러도 지원합니다. 다른 응용 프로그램은 QEMU를 사용하여 다른 아키텍처의 실행 파일 을 투명하게 실행하는 것 입니다.
POSIX가 shebang을 지정 하지는 않는다고 생각 합니다 : https://unix.stackexchange.com/a/346214/32558 비록 이론적 근거 섹션과 시스템에서 실행 가능한 스크립트가 지원되는 경우 우연히 있다". 그러나 macOS와 FreeBSD도 그것을 구현하는 것 같습니다.
PATH
검색 동기
아마도 shebang의 존재에 대한 큰 동기는 Linux에서 종종 PATH
다음과 같이 명령을 실행하려고한다는 사실입니다 .
basename-of-command
대신에:
/full/path/to/basename-of-command
그러나 shebang 메커니즘이 없으면 Linux가 각 유형의 파일을 실행하는 방법을 어떻게 알 수 있습니까?
명령에서 확장자를 하드 코딩하십시오.
basename-of-command.py
또는 모든 인터프리터에서 PATH 검색을 구현하십시오.
python basename-of-command
가능성이 있지만, 명령을 다른 언어로 리팩토링하기로 결정하면 모든 것이 깨지는 주요 문제가 있습니다.
Shebangs는이 문제를 아름답게 해결합니다.
기술적으로 파이썬에서 이것은 주석 줄입니다.
이 행은 쉘에서 (명령 행에서) py 스크립트를 실행하는 경우에만 사용됩니다 . 이것은 " 세방 "으로 알려져 있습니다 . 파이썬 스크립트뿐만 아니라 다양한 상황에서 사용됩니다.
여기서는 쉘 이 파일의 나머지 부분을 처리하기 위해 특정 버전 의 Python 을 시작하도록 지시 합니다.
py.exe
. 이것은 표준 Python 설치의 일부입니다.
이를 수행하는 주된 이유는 운영 체제 환경에서 스크립트를 이식 가능하게하기위한 것입니다.
예를 들어 mingw에서 파이썬 스크립트는 다음을 사용합니다.
#!/c/python3k/python
GNU / Linux 배포판에서는 다음 중 하나입니다.
#!/usr/local/bin/python
또는
#!/usr/bin/python
그리고 최고의 상용 유닉스 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 인터프리터입니다. 아치 리눅스는 오랫동안 파이썬 3으로 기본 설정되어 있으며, 파이썬 2는 2020
가장 많이 놓친 부분 중 하나를 강조하면 이해하는 데 도움이 될 수 있습니다. python
터미널에 입력하면 일반적으로 전체 경로를 제공하지 않습니다. 대신, 실행 파일이 PATH
환경 변수 에서 조회 됩니다. 차례로 파이썬 프로그램을 직접 실행 /path/to/app.py
하려면 쉘에 어떤 인터프리터를 사용할 것인지 ( 해시 뱅을 통해 다른 제공자가 위에서 설명한 내용) 알려 주어야합니다 .
Hashbang 은 통역사에게 완전한 길 을 기대 합니다. 따라서 Python 프로그램을 직접 실행하려면 특히 virtualenv 사용을 고려할 때 크게 변하는 Python 이진의 전체 경로를 제공해야합니다 . 휴대 성을 해결하기 위해 트릭 /usr/bin/env
이 사용됩니다. 후자는 원래 환경을 변경하고 명령을 실행하기위한 것입니다. 변경 사항이 제공되지 않으면 현재 환경에서 명령을 실행 PATH
하여 트릭을 수행하는 동일한 조회를 효과적으로 수행합니다.
권장되는 방법으로 설명서에 제안되어 있습니다.
2.2.2. 실행 가능한 파이썬 스크립트
BSD'ish Unix 시스템에서 파이썬 스크립트는 쉘 스크립트와 같이 직접 실행하여 직접 실행 가능하게 만들 수 있습니다
#! /usr/bin/env python3.2
에서 http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
사용하려는 인터프리터 만 지정합니다. 이를 이해하려면을 수행하여 터미널을 통해 파일을 작성한 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
python2는 인쇄 연산자를 지원하기 때문에 stdout으로 인쇄 하면 작동합니다. 이제 스크립트 인터프리터 간을 전환하는 방법을 배웠습니다.
그 줄없이 파일이 동일하게 실행되는 것처럼 보입니다.
그렇다면 Windows에서 Python 프로그램을 실행하고 있습니까? Windows는이 줄을 사용하지 않고 파일 확장명을 사용하여 파일 확장명과 관련된 프로그램을 실행합니다.
그러나 2011 년에는 "파이썬 런처" 가 개발되어 Windows 용 Linux 동작을 어느 정도 모방했습니다. 이것은 어느 파이썬 인터프리터가 실행 될지 선택하는 것만으로 제한됩니다 (예 : 둘 다 설치된 시스템에서 파이썬 2와 파이썬 3 중에서 선택). 런처는 선택적 py.exe
으로 Python 설치에 의해 설치되며 .py
파일 과 연관 될 수 있으므로 런처가 해당 행을 확인한 다음 지정된 Python 인터프리터 버전을 시작합니다.
$ python myscript.py
.
이는 "실제"답변보다 더 많은 과거 정보를 의미합니다.
당신은 누구의 디자이너 모든 물건을 넣을 수있는 위치의 자신의 개념을 가지고, 때로는 파이썬, 펄, 배쉬, 또는 다른 GNU / 오픈 소스 물건을 많이 포함되지 않은 운영 체제와 같은 유닉스의 제비가 있었다 하루에 그 뒤로 기억 에 모두를 .
다른 Linux 배포판에서도 마찬가지입니다. Linux에서 pre-FHS [1]-/ usr / bin / 또는 / usr / local / bin /에 파이썬이있을 수 있습니다. 또는 설치되지 않았을 수도 있으므로 직접 빌드하고 ~ / bin에 넣습니다.
솔라리스는 제가 버클리 유닉스에서 시스템 V로 전환하면서 최악의 작업을 해왔습니다. 일부 정말 긴 경로. 각 패키지를 자체 디렉토리에 설치하는 Sunfreeware.com의 기억이 있지만 바이너리가 / usr / bin에 심볼릭 링크되어 있는지 여부를 기억할 수 없습니다.
아, 때로는 / usr / bin이 NFS 서버에있었습니다 [2].
따라서이 env
문제를 해결하기 위해 유틸리티가 개발되었습니다.
그럼 당신은 쓸 수 #!/bin/env interpreter
및 경로만큼 적절한 일이 있었다 합리적인 실행의 기회를. 물론 합리적인 환경 변수 (Python 및 Perl)도 적절한 환경 변수를 설정했음을 의미합니다. bash / ksh / zsh의 경우 방금 작동했습니다.
이것은 사람들이 쉘 스크립트 (perl 및 python과 같은)를 전달했기 때문에 중요했으며 Red Hat Linux 워크 스테이션에서 / usr / bin / python을 하드 코딩했다면 SGI에서 나빠질 것입니다 ... IRIX가 파이썬을 올바른 자리에 넣었다고 생각합니다. 그러나 Sparc 스테이션에서는 전혀 실행되지 않을 수 있습니다.
나는 sparc 역을 그리워한다. 그러나 많이는 아닙니다. 자, 이제 이베이에서 트롤링을하게되었습니다. Bastages.
[1] 파일 시스템 계층 표준. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] 그렇습니다. 때때로 사람들은 여전히 그런 일을합니다. 그리고 아니오, 나는 순무 또는 양파를 벨트에 착용하지 않았습니다.
가상 환경에서 스크립트를 실행하는 경우, 예 를 들어 작업 venv
하는 which python
동안 실행 venv
하면 Python 인터프리터의 경로가 표시됩니다.
~/Envs/venv/bin/python
가상 환경 의 이름은 Python 인터프리터의 경로에 포함 되어 있습니다. 따라서 스크립트에서이 경로를 하드 코딩하면 두 가지 문제가 발생합니다.
따라서 Jonathan 의 답변 에 추가하기 위해 이상적인 Shebang은 #!/usr/bin/env python
OS 간 이식성뿐만 아니라 가상 환경에서도 이식성입니다!
python2
와 사이의 이식성 문제를 고려할 때 python3
프로그램이 두 버전과 호환되지 않으면 항상 두 버전을 지정해야합니다.
일부 배포판 배송됩니다 python
에 심볼릭 링크 python3
지금 잠시 동안 -에 의존하지 않는 python
것 python2
.
이것은 PEP 394에 의해 강조됩니다 .
플랫폼 간 차이를 허용하려면 Python 인터프리터를 호출해야하는 모든 새 코드는 python을 지정하지 말고 python2 또는 python3 (또는보다 구체적인 python2.x 및 python3.x 버전을 지정해야합니다. 마이그레이션 노트 참조 ) . 쉘 스크립트에서 호출 할 때, system () 호출을 통해 호출 할 때 또는 다른 컨텍스트에서 호출 할 때 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())
#!/usr/bin/env python
맨 위에 표시하는 CGI 스크립트 (.py) .