How to refer to data files without hardcoding paths?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Tue Sep 8 04:57:01 CEST 2009


En Sun, 06 Sep 2009 10:44:38 -0300, Timothy Madden
<terminatorul at gmail.com> escribió:
> Matthew Wilson wrote:

>> When a python package includes data files like templates or images,
>> what is the orthodox way of referring to these in code?
>>  I also came across pkg_resources, and that seems to work, but I don't
>> think I understand it all yet.
>
> sys.path[0] should give you the path to your script. By reading the  
> documentation I would say it would give the path to the first script  
> passed to the interpreter at launch, but after using it I find it also  
> gives the current script path inside an imported file. So I use it to  
> group the script files in my application into subdirectories, and import  
> them as necessary from there.

No, I think you got it wrong. sys.argv[0] is the name of the script being
executed; you can get its full path using os.path.abspath(sys.argv[0])
sys.path[0] is the directory containing the script being executed right
when the program starts. Later, any module is free to add and remove
entries from sys.path, so one should not rely on sys.path[0] being that
specific directory.

What you refer as "script files" are actually modules, and they're
imported, not executed. There is only one script being executed, the one
named in the command line (either as `python scriptname.py` or
`scriptname.py` or just `scriptname` or by double-clicking scriptname.py)

> My app works regardless of the current working directory, and can import  
> scripts and load icons from its various subdirectories.
>
> Still I would like to know why it works in imported scripts, since the  
> doc page says sys.path[0] is the path to the script that caused the  
> interpreter to launch. What would that mean ?

The script that is being executed, scriptname.py in the example above.
Even if you later import module `foo` from package `bar`, sys.argv[0]
doesn't change.

To determine the directory containing the main script being executed, put
these lines near the top of it:

import os,sys
main_directory = os.path.dirname(os.path.abspath(sys.argv[0]))

You may locate other files relative to that directory. But that doesn't
work if some components aren't actually on the filesystem (egg files,
zipped libraries, or programs deployed using py2exe or similar). I prefer
to use pkgutil.get_data(packagename, resourcename) because it can handle
those cases too.

-- 
Gabriel Genellina




More information about the Python-list mailing list