why use #!/usr/bin/env python rather than #!python?

  • Thread starter Adriano Ferreira
  • Start date
A

Adriano Ferreira

Many Python scripts I see start with the shebang line

#!/usr/bin/env python

What is the difference from using just

#!python

Regards,
Adriano.
 
K

Klaus Alexander Seistrup

Adriano said:
Many Python scripts I see start with the shebang line

#!/usr/bin/env python

What is the difference from using just

#!python

#v+

$ ls -l /tmp/hello.py
-rwxr-xr-x 1 klaus klaus 38 2005-12-02 14:59 /tmp/hello.py
$ cat /tmp/hello.py
#! python
print 'Hello, world!'
# eof
$ /tmp/hello.py
bash: /tmp/hello.py: python: bad interpreter: No such file or directory
$

#v-

Cheers,
 
A

Adriano Ferreira

#v+

$ ls -l /tmp/hello.py
-rwxr-xr-x 1 klaus klaus 38 2005-12-02 14:59 /tmp/hello.py
$ cat /tmp/hello.py
#! python
print 'Hello, world!'
# eof
$ /tmp/hello.py
bash: /tmp/hello.py: python: bad interpreter: No such file or directory
$

#v-

Hey, that's not fair. In your illustration above, does 'python' can be
found in the PATH? That is,

$ python /tmp/hello.py

works? If it does, probably

#!/usr/bin/python
#!/usr/bin/env python
#!python

would also work if
(1) 'python' is at '/usr/bin/python' (but that's inflexible)
(2) 'python' can be found in the environment variable path (if 'env'
is at '/usr/bin/env')
(3) 'python' can be found in the environment variable path (no need
for 'env' utility)

Cheers,
Adriano.
 
K

Klaus Alexander Seistrup

Adriano Ferreira skrev:
Hey, that's not fair. In your illustration above, does 'python' can be
found in the PATH? That is,

$ python /tmp/hello.py

works? If it does, probably

#!/usr/bin/python
#!/usr/bin/env python
#!python

would also work if
(1) 'python' is at '/usr/bin/python' (but that's inflexible)
(2) 'python' can be found in the environment variable path (if 'env'
is at '/usr/bin/env')
(3) 'python' can be found in the environment variable path (no need
for 'env' utility)

Sure, I wasn't fair. But look here:

#v+

$ python /tmp/hello.py
Hello, world!
$ which python
/usr/bin/python
$

#v-

I do not know the syntax of the shebang-line, but perhaps an absolute
path is required?

PS: The "Mail-Copies-To: nobody" header line means that I do not wish
to receive mail replies - please follow-up to group only.

Cheers,
 
C

Carsten Haese

Hey, that's not fair. In your illustration above, does 'python' can be
found in the PATH? That is,

$ python /tmp/hello.py

works? If it does, probably

#!/usr/bin/python
#!/usr/bin/env python
#!python

would also work if
(1) 'python' is at '/usr/bin/python' (but that's inflexible)
(2) 'python' can be found in the environment variable path (if 'env'
is at '/usr/bin/env')
(3) 'python' can be found in the environment variable path (no need
for 'env' utility)

(3) assumes that whatever shell the user is running looks up the shebang
executable in the path, which bash, just to name one example, does not
do.

(2) and (1) require that you know where env and python live,
respectively, that's true, but env is likely to be found in an
OS-dependent standard location than python, so (2) is preferable.

HTH,

Carsten.
 
A

Adriano Ferreira

(3) assumes that whatever shell the user is running looks up the shebang
executable in the path, which bash, just to name one example, does not
do.

I think that was the answer I was looking for. So that "#!/usr/bin/env
python" is more portable than "#! python" and that's probably why it
worked for me with cygwin/bash but not for Klaus on whatever platform
he used.
(2) and (1) require that you know where env and python live,
respectively, that's true, but env is likely to be found in an
OS-dependent standard location than python, so (2) is preferable.

I agree. Only a very strange Unix-like installation would not have
'env' at '/usr/bin/env'.

Many thanks to Klaus and Carsten for helping me find out why this
convention is helpful/useful.

Best regards,
Adriano
 
K

Klaus Alexander Seistrup

Adriano said:
So that "#!/usr/bin/env python" is more portable than "#! python"
and that's probably why it worked for me with cygwin/bash but not
for Klaus on whatever platform he used.

/me is using bash on linux.
I agree. Only a very strange Unix-like installation would not have
'env' at '/usr/bin/env'.

According to <http://www.in-ulm.de/~mascheck/various/shebang/>:

»However, env(1) is not /usr/bin/env but /bin/env at least on
Unicos 9.0.2, OpenServer 5.0.6 and IIRC on at least one older
Linux distribution. Free-, Net- and OpenBSD in turn only come
with /usr/bin/env. So the env-mechanism is increasing conven-
ience, but not strictly assuring portability.«

Cheers,
 
A

Adriano Ferreira

/me is using bash on linux.

I think that was not a bash issue in my case, but a Cygwin/Win32
issue. Windows has some monstruous oddities in order to assure broken
behavior of yesterday is here today in the name of compatibility.
Examples of these everlasting broken behaviors in Windows are looking
at current directory and path no matter what you say. Cygwin isn't
immune to this.
According to <http://www.in-ulm.de/~mascheck/various/shebang/>:

»However, env(1) is not /usr/bin/env but /bin/env at least on
Unicos 9.0.2, OpenServer 5.0.6 and IIRC on at least one older
Linux distribution. Free-, Net- and OpenBSD in turn only come
with /usr/bin/env. So the env-mechanism is increasing conven-
ience, but not strictly assuring portability.«

That is to the point. Thanks.

Adriano.
 
D

Donn Cave

Adriano Ferreira said:
Hey, that's not fair. In your illustration above, does 'python' can be
found in the PATH? That is,

$ python /tmp/hello.py

works? If it does, probably

#!/usr/bin/python
#!/usr/bin/env python
#!python

would also work if
(1) 'python' is at '/usr/bin/python' (but that's inflexible)
(2) 'python' can be found in the environment variable path (if 'env'
is at '/usr/bin/env')
(3) 'python' can be found in the environment variable path (no need
for 'env' utility)

Contrary to popular belief, #! is not intended for the shell,
but rather for the execve(2) system call of the UNIX operating
system. These two characters form the 16 bit "magic number"
of interpreter files. Any executable file must start with a
16 bit field that identifies it so the operating system will
know how to execute it.

In the case of a #! interpreter file, the operating system
expects the rest of that line to be the path to the file.
PATH is not searched, and is irrelevant. The only way
#!python can work, is if it's in the current working directory.

Just to help make it confusing, when this mechanism fails
and execve(2) returns an error, most shells will go on to
try to execute the file themselves, regardless of whether
there's a #! or not. csh (the shell language that doesn't
look anything like C, Bill Joy's attempt at language design
before he started over with Java) does that only if the first
line is "#"; otherwise it invokes the Bourne shell.

Donn Cave, (e-mail address removed)
 
M

Mike Meyer

Carsten Haese said:
(3) assumes that whatever shell the user is running looks up the shebang
executable in the path, which bash, just to name one example, does not
do.

For the record, on a modern Unix system, #! isn't handled by the
shell; it's handled by the kernel. #! is a "magic number" denoting a
type of executable. Some shells used to do that, and may still do that
if the underlying system doesn't handle it.

<mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top