[Tutor] running modules as scripts

Steven D'Aprano steve at pearwood.info
Fri Dec 6 03:22:35 CET 2013


On Thu, Dec 05, 2013 at 01:20:05PM -0500, ugajin at talktalk.net wrote:

> I have some difficulty with the abovet. I succeeded after a fashion, 
> but only after some experiment, and I am not satisfied that all is 
> well. Here is the script code (as per the Python tutorial 6.1.1.):

> It is saved in the current directory as fibo.py with the current 
> directory being: 
> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/

I doubt that is the current directory. Unless you type:

cd /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/

at the terminal, it won't be the current directory.

There are three important concepts for you to understand:

1) The Python path. This is a set of directories that Python will search 
when *importing* a module. The Python path includes the location of 
Python's standard library modules. As a general rule, you should not 
mess with the standard library -- don't change the files there, don't 
remove them, and don't add your own into the same location.

Instead, you should designate a folder in your home directory for your 
own Python scripts, and put them all in that. For advanced users, you 
can violate this rule -- the Python path is user-editable to allow that. 
But you need to know what you are doing.

2) The current, or working, directory. This is a concept from the 
operating system and shell, and Python inherits the concept from them. 
Think of it as meaning "the directory (folder) you are currently in", 
and at the terminal you change the working directory with the cd 
command.

3) The path to a file, which may be an absolute path, or a relative 
path. In Mac, Unix and Linux, absolute paths start with / (slash). 
Relative paths do not, and are treated as relative from the current 
working directory.

The end result is this: if you create a file called "fibo.py" and place 
it somewhere in the Python path (including in Python's own standard 
library, which is not a good idea), then you can import that module in 
Python. You can also run that module with the -m switch by giving the 
module name, which excludes the .py extension:

python -m fibo

and Python will search all the appropriate places for a module like 
fibo.py or fibo.so or similar, import it, then run it as a script. This 
will work wherever you are (the working directory), since it uses 
Python's own search path for modules.

On the other hand, if you run a file directly, you need to give the path 
to the file. You can give an absolute path:

python /home/ugajin/scripts/fibo.py  # for example

or you can change the working directory and then give a relative path:

cd /home/ugajin/
python scripts/fibo.py

or 

cd /home/ugajin/scripts
python fibo.py


or similar. Basically, if running ls shows you the file you want to run, 
you can run it directly, otherwise you need to give a path to it.

So you can see, when you give a file name as argument, Python does not 
search the sys.path to find the file, it needs to be given full 
directions to reach it -- either as a path relative to the current 
working directory (which you set with cd) or an absolute path starting 
with a slash.


[...]
> And. . .  if I open the same script with: right click > Open with > Python Launcher.app (2.7.6) I get:
> Last login: Wed Dec  4 20:52:15 on ttys002
> Apples-iMac-4:~ apple$ cd '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/' && '/usr/bin/pythonw'  '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/fibo.py'  && echo Exit status: $? && exit 1
> Traceback (most recent call last):
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/fibo.py", line 21, in <module>
>     fib(int(sys.argv[1]))
> IndexError: list index out of range


This error is easy to explain: since you're running the script with the 
right-click option, there's no command line arguments given, and 
sys.argv is the empty list []. Since there are no items in sys.argv, 
sys.argv[1] will fail with IndexError.


> Then . . . if I then use this same window to call the script it runs:
> Apples-iMac-4:python2.7 apple$ python fibo.py 50
> 1 1 2 3 5 8 13 21 34

And this succeeds because you have (inadvertently) changed the working 
directory to the location of the file.


My recommendation is:

- In your home directory, create a folder called "scripts", and 
  put all *your* Python files in that. Leave Python's own files 
  where you found them.

- Do you know how to edit your shell's config files? On Linux, 
  I would say:

  nano ~/.bashrc

  but I'm not sure what the Mac equivalent is. In any case, edit
  your config file to include the line:

  export PYTHONPATH="/home/ugajin/scripts/"

  (or whatever the path to your scripts directory actually is).
  This is optional but will make importing scripts easier.

- After you have done this, then either of these lines ought to
  work from any working directory:

  python -m fibo 50
  python ~/scripts/fibo.py 50



Feel free to ask any additional questions!


-- 
Steven


More information about the Tutor mailing list