usethedeathstar
usethedeathstar

Reputation: 2309

python package import from different directory

I have the following directory structure:

\something\python\
    extras\
        __init__.py # empty file
        decorators.py # contains a benchmark decorator (and other things)
    20131029\   # not a package, this contains the scripts i use directly by doing "python somethingelse.py"
        somethingelse.py

And now I want to be able to do something like

from .extras import decorators
from decorators import benchmark

from inside somethingelse.py

For this to work, where do I need to place __init__.py files, (at the moment, the "\something\python\" path is added to my .tchsrc )

Now, i get the following error:

 from .extras import decorators
ValueError: Attempted relative import in non-package

Is this a problem with adding it to my pythonpath? or how should I solve this? The current workaround I have is to just copypaste the decorators.py into each new directory i make (if I make a new version of my code, like the "20131029"), but that is just a stupid workaround which means I have to copypaste a lot of stuff each time i make a new version of my code, so a more elegant version with the correct imports is what I want.

Note: I am working in python 2.7, if that makes any difference?

edit: yes, i run it by doing

python somethingelse.py

more edit: no idea if the way that the benchmark decorator is defined matters? (it is not a class or so, the next thing comes exactly out of the decorators.py file)

import time, functools
def benchmark(func):
    """
    A decorator that prints the time a function takes
    to execute.
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        t = time.time()
        res = func(*args, **kwargs)
        print func.__name__, time.time()-t
        return res
    return wrapper

Edit: if i put the \something\python\extras\ to my pythonpath, i get

ImportError: No module named decorators

when i run:

from decorators import benchmark

Does this mean that inside that extras-directory i need to make another subdirectory, in which i than put the decorators.py?

edit: in the .tchsrc, i added the following line:

setenv PYTHONPATH /bla/blabla/something/python/extras/

and in the somethingelse.py, if i run the following:

import sys
s = sys.path
for k in s:
    print k

i find that the path /bla/blabla/something/python/extras/ is in that list, so i do not get why it does not work?

Upvotes: 0

Views: 6737

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121486

Your 20131029 directory is not a package, so you cannot use relative import paths beyond it.

You could add the extras directory to your Python module search path, using a relative path from your current script:

import sys, os

here = os.path.dirname(os.path.abspath(__file__))

sys.path.insert(0, os.path.normpath(os.path.join(here, '../extras')))

Now imports look for modules in the extras directory first, so use:

import decorators

Because your directory name itself is using only digits, you cannot make that a package anyway; package names must stick to Python identifier rules, which cannot start with a digit. Even if you renamed the directory, and added a __init__.py file, you still cannot use it is as package when you run a file within the directory as a script; scripts are always considered to live outside a package. You'd have to have a top-level 'shim' script that imports the real code from a package:

from package_20131029.somethingelse import main

main()

Upvotes: 3

Related Questions