Running a python script under Linux

A

Andrew Robinson

I understand this is not exactly a Python question, but it may be of
interest to other Python programmers, so I'm asking it here instead of a
more generic Linux group.

I have a Centos system which uses Python 2.4 as the system Python, so I
set an alias for my personal use:

[steve@ando ~]$ which python
alias python='python2.7'
/usr/local/bin/python2.7


When I call "python some_script.py" from the command line, it runs under
Python 2.7 as I expected. So I give the script a hash-bang line:

#!/usr/bin/env python

and run the script directly, but instead of getting Python 2.7, it runs
under Python 2.4 and gives me system errors.

When I run env directly, it ignores my alias:

steve@ando ~]$ /usr/bin/env python -V
Python 2.4.3


What am I doing wrong?

After seeing the lecture on Bad Ideas ... this might backfire on me.... :)

But ... if you really want to make the alias show up in all bash shells,
you can put it in your ~/.bashrc file which is executed every time a
shell is created.
alias python='python2.7'

However, alias expansions do not work in non-interactive shells -- so I
don't think it will launch with the #!/bin/env technique.

OTOH -- Shell functions DO operate in non-interactive mode, so you could
add something like:

function python() {
python3 # whichever version of python you want as default
}
# eof of function example to add to ~/.bashrc

OR............
In a bash shell, you can also do:

function python {
python3 # or 2.7 ...
}
export -f python

And that would give the same effect as an alias, but funtions can be
exported to child processes.

It's your system, and we're adults here -- screw it up however you want to.
Cheers!
 
A

Andrew Robinson

What am I doing wrong?
By the way, I didn't include command line parameters as part of the
function definition, so you might want to add them to insure it acts
like a generic alias.

Also, (alternately), you could define a generic python shell
script/import with the duty of checking for a compatible python version;
and if the wrong one is executing -- it could then import the shell
command execution function, and *fork* the correct version of python on
the script; then it could exit.

.... or whatever.... ;)
 
S

Steven D'Aprano

I understand this is not exactly a Python question, but it may be of
interest to other Python programmers, so I'm asking it here instead of a
more generic Linux group.

I have a Centos system which uses Python 2.4 as the system Python, so I
set an alias for my personal use:

[steve@ando ~]$ which python
alias python='python2.7'
/usr/local/bin/python2.7


When I call "python some_script.py" from the command line, it runs under
Python 2.7 as I expected. So I give the script a hash-bang line:

#!/usr/bin/env python

and run the script directly, but instead of getting Python 2.7, it runs
under Python 2.4 and gives me system errors.

When I run env directly, it ignores my alias:

steve@ando ~]$ /usr/bin/env python -V
Python 2.4.3


What am I doing wrong?
 
C

Cameron Simpson

| I understand this is not exactly a Python question, but it may be of
| interest to other Python programmers, so I'm asking it here instead of a
| more generic Linux group.
|
| I have a Centos system which uses Python 2.4 as the system Python, so I
| set an alias for my personal use:
|
| [steve@ando ~]$ which python
| alias python='python2.7'
| /usr/local/bin/python2.7
|
|
| When I call "python some_script.py" from the command line, it runs under
| Python 2.7 as I expected. So I give the script a hash-bang line:
|
| #!/usr/bin/env python
|
| and run the script directly, but instead of getting Python 2.7, it runs
| under Python 2.4 and gives me system errors.
|
| When I run env directly, it ignores my alias:
|
| steve@ando ~]$ /usr/bin/env python -V
| Python 2.4.3
|
|
| What am I doing wrong?

You're assuming aliases are exported. They are not. (I've seen ksh
present exportable aliases, but IMO it is a bad idea anyway.)

You're (slightly) better off putting a python symlink in /usr/local/bin, but
that may break arbitrary other things (as, indeed, would your #! incantation
were it effective). Also a bad idea though.

Regarding aliases, I would make a "py27" alias for my personal typing
convenience perhaps, but _not_ try to make the command "python" run
anything but the system default python (24, as you say).

When I need a particular minimum revision of python I use one of my
"py25+", "py26+", "py27+", "py30+" etc wrapper scripts. Code for "py25+"
here:

https://bitbucket.org/cameron_simpson/css/src/tip/bin/py25+

This has the advantages of not conflicting with a system name like
"python" and also is usable with your #! incantation, which requires an
executable file after "env".

Cheers,
 
J

Jussi Piitulainen

Steven said:
I have a Centos system which uses Python 2.4 as the system Python, so I
set an alias for my personal use:

[steve@ando ~]$ which python
alias python='python2.7'
/usr/local/bin/python2.7


When I call "python some_script.py" from the command line, it runs under
Python 2.7 as I expected. So I give the script a hash-bang line:

#!/usr/bin/env python

and run the script directly, but instead of getting Python 2.7, it runs
under Python 2.4 and gives me system errors.

When I run env directly, it ignores my alias:

steve@ando ~]$ /usr/bin/env python -V
Python 2.4.3

The alias is known only to the shell for which it is defined. The
shell does nothing with it when it occurs in an argument position. So
env receives just the six-letter string "python" which it resolves as
a program name by walking the file system along your PATH until it
finds the program.

Why not just set your PATH so that the python that is python2.7 is
found first. If this breaks something, your alias would also have
broken that something if aliases worked the way you wanted. Try.
 
H

Hans Mulder

I understand this is not exactly a Python question, but it may be of
interest to other Python programmers, so I'm asking it here instead of a
more generic Linux group.

I have a Centos system which uses Python 2.4 as the system Python, so I
set an alias for my personal use:

[steve@ando ~]$ which python
alias python='python2.7'
/usr/local/bin/python2.7


When I call "python some_script.py" from the command line, it runs under
Python 2.7 as I expected. So I give the script a hash-bang line:

#!/usr/bin/env python

and run the script directly, but instead of getting Python 2.7, it runs
under Python 2.4 and gives me system errors.

When I run env directly, it ignores my alias:

steve@ando ~]$ /usr/bin/env python -V
Python 2.4.3


What am I doing wrong?

You're using an alias. Aliases are not normally exported, and
even if they are (e.g. ksh can be configure to export aliases),
env doesn't recognize them.

What would work, is changing your PATH environment variable
so that the first python on your PATH is the one you want,
or a symlink pointing to it.

The Pythonic way to get what you want, is to be explicit:

#!/usr/local/bin/python2.7 -V

If you do that, it will even work in situations where you
can't control PATH, such as CGI scripts and cron jobs.

There are situations where using #!/usr/bin/env makes sense,
but yours isn't one of them.

Hope this helps,

-- HansM
 
D

D'Arcy J.M. Cain

The Pythonic way to get what you want, is to be explicit:

#!/usr/local/bin/python2.7 -V

If you do that, it will even work in situations where you
can't control PATH, such as CGI scripts and cron jobs.

As long as you only run on one system that's OK. That won't work on
NetBSD or Linux[1] for example.
There are situations where using #!/usr/bin/env makes sense,
but yours isn't one of them.

#! /usr/bin/env python2.7

[1]: Well, Ubuntu anyway. I don't know about the others.
 
H

Hans Mulder

As long as you only run on one system that's OK.

As I understand it, the OP has a single system where the
system Python is CPython 2.4, and he has install 2.7 in
/usr/local/bin.
That won't work on NetBSD or Linux[1] for example.

I would expect it to work, as long as /usr/local/bin/python2.7
exists and is a binary executable for the right architecture.

Why wouldn't it work?

It doesn't exceed the 32-character limit and it contains
only one option. What other pitfalls are there?
#! /usr/bin/env python2.7

On my box, that line might find a python2.7 in the
currently active virtualenv, which may have the wrong
set of third-party modules in its site-packages.

When I write a script that is meant to be used as a
utility, independent of which virtualenv is currently
active, then I'll make sure that its #! line points
at the Python2.7 install I used to test it.
[1]: Well, Ubuntu anyway. I don't know about the others.


Just curious,

-- HansM
 
M

Michael Torrie

When I call "python some_script.py" from the command line, it runs under
Python 2.7 as I expected. So I give the script a hash-bang line:

#!/usr/bin/env python

and run the script directly, but instead of getting Python 2.7, it runs
under Python 2.4 and gives me system errors.

When I run env directly, it ignores my alias:

steve@ando ~]$ /usr/bin/env python -V
Python 2.4.3


What am I doing wrong?

Hash-bang isn't a shell function; it's a kernel function. There's no
reason why a shell setting (alias) would be known to the kernel.
Different shells have different ideas about aliases anyway. And the
program that the she-bang tells the kernel to run is /usr/bin/env, again
something that doesn't have anything to do with the shell. The only
thing the shell can communicate to the env program is the environment,
including the PATH variable, which env searches.

The reason it works this way is that the shell is simply another program
that can be replaced. One could make a shell based on python, and it
might replace the bash "alias" command with a completely different
mechanism.

When I was first exposed to Linux, it took me a long time to understand
and appreciate how basic commands like ls and env are not part of shell
at all, unlike my experience with the DOS and Windows command.com and
cmd.exe shells. At first I found this archaic and frustrating. But
later I realized the great power of doing things this way. If I didn't
like the way ls listed things, I could change it; replace ls easily. I
remember seeing TSRs (remember them!) that would hook into command.com
and patch it to add or alter command.com commands. The Unix way was
definitely cleaner.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top