114

I'm developing/testing a package in my local directory. I want to import it in the interpreter (v2.5), but sys.path does not include the current directory. Right now I type in sys.path.insert(0,'.'). Is there a better way?

Also,

from . import mypackage

fails with this error:

ValueError: Attempted relative import in non-package
cweiske
  • 30,033
  • 14
  • 133
  • 194
projectshave
  • 3,771
  • 5
  • 23
  • 24
  • Where did you read that "." was a Python module? – S.Lott Jul 11 '09 at 01:40
  • 16
    @Lott: It's a relative import path described here: http://docs.python.org/reference/simple_stmts.html#the-import-statement – projectshave Jul 11 '09 at 02:41
  • 1
    You may want to look at this definitive guide https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-imports.html – Kevin Zhu Jun 08 '18 at 07:14
  • 1
    Your problem is probably different, but my problem was just that I left the ".py" extension on it after the import statement, which causes it to fail with the error "ModuleNotFoundError: No module named 'myFile.py'; 'myFile' is not a package". Also, the cwd is not explicitly in my sys.path for Python 3.8.10 shell run from terminal either, though it is in the Python 3.8.10 IDLE shell, and in both cases an empty string is. – H. H. Mar 13 '23 at 23:09

10 Answers10

59

You can use relative imports only from in a module that was in turn imported as part of a package -- your script or interactive interpreter wasn't, so of course from . import (which means "import from the same package I got imported from") doesn't work. import mypackage will be fine once you ensure the parent directory of mypackage is in sys.path (how you managed to get your current directory away from sys.path I don't know -- do you have something strange in site.py, or...?)

To get your current directory back into sys.path there is in fact no better way than putting it there.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • Python 2.5 for Ubuntu 8.10 does not have the current directory (empty string) in sys.path for the interpreter. I didn't change anything, so it somehow got shipped that way. I just installed 3.0 and sys.path DOES have '' in sys.path. – projectshave Jul 11 '09 at 03:01
  • @projectshave, OK, Ubuntu's no doubt got their reasons! I haven't noticed that in 8.04 (what we currently use at work) but maybe I just wasn't paying enough attention. – Alex Martelli Jul 11 '09 at 03:31
  • 1
    I am partially wrong. Python invoked from a shell has the current directory in sys.path. Python invoked from Emacs does not have the current directory. Strange. – projectshave Jul 21 '09 at 16:10
  • 1
    Ah well, then it's Emacs who's got their reasons as opposed to Ubuntu's (as a vim user I don't really know;-). You can conditionally insert '.' in your sys.path iff not there of course. – Alex Martelli Jul 21 '09 at 18:25
  • @Alex Martelli: Thank you so much! I've been searching and searching for the solution to why my add-on (for Anki) needed a different import statement when being run 'locally' as a script. When I instead added a local_launch() method and imported/launched the whole thing from a script *outside* the package folder, it worked like a charm! – Jon Coombs Jan 30 '14 at 18:33
21

See the documentation for sys.path:

http://docs.python.org/library/sys.html#sys.path

To quote:

If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first.

So, there's no need to monkey with sys.path if you're starting the python interpreter from the directory containing your module.

Also, to import your package, just do:

import mypackage

Since the directory containing the package is already in sys.path, it should work fine.

SpoonMeiser
  • 19,918
  • 8
  • 50
  • 68
  • 2
    It will fail if a similar file name exists somewhere else in the working env. – JAR.JAR.beans Jun 07 '16 at 12:45
  • @JAR.JAR.beans the current working directory should be the first thing in `sys.path` so files there should be found before files anywhere else in the working environment. – SpoonMeiser Jun 07 '16 at 12:59
  • 3
    Good point. That is, if we run the file from the local directory. In the case it's some other folder, and in the case a change to sys.path is needed - it means `sys.path.insert(0, new_path)` rather than `sys.path.append(new_path)`. – JAR.JAR.beans Jun 07 '16 at 13:35
20

Keep it simple:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Community
  • 1
  • 1
Guido U. Draheim
  • 3,038
  • 1
  • 20
  • 19
  • 12
    I like this solution, it is the most simple. The only remaining question is why did the "only one way to do it" rule has been deemed optional when implementing imports ... Seriously there is about 15 ways to declare and organize the packages, all of which have drawbacks – Léo Germond May 25 '16 at 08:35
  • using an exception for other purposes than raising an exception is a bad coding style, this should be avoided at any cost – LPVOID Jan 21 '23 at 17:15
  • @LPVOID catching exceptions is common practice in python. It is not bad coding style (although `except: ImportError` might be better style in this case). – ForeverWintr Feb 10 '23 at 05:52
  • @ForeverWintr yeah, I guess this approach is popular amongst python devs because python is a dynamically typed language, and it is much quicker to use exception than analyzing the type of a variable. But this all doesn't make it an innocent approach, IMHO it is just a lazy and bad coding style. – LPVOID Feb 12 '23 at 06:13
  • Naahh, ForeverWintr is quite right here. This is common practice. Atleast for the case of local imports, even static code checkers like mypy can get away with it. - And by the way, in production code I used to catch ImportError although it may be better to switch to ModuleNotFoundError. The mere existance of that exception class (in python 3.6) points to the fact that people were catching import-errors for a long time. @lpvoid – Guido U. Draheim Feb 12 '23 at 23:28
  • @GuidoU.Draheim I would have to disagree with you my friend, the fact that it's a common practice does not make it a good coding style. The majority of developers are average developers and most of them have no "time" for a good coding style, usually due to deadlines or cost. – LPVOID Feb 15 '23 at 17:43
17

If you want to run an unmodified python script so it imports libraries from a specific local directory you can set the PYTHONPATH environment variable - e.g. in bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

If you just want it to import from the current working directory use the . notation:

export PYTHONPATH=.
python myscript.py
Pierz
  • 7,064
  • 52
  • 59
  • Exporting PYTHONPATH includes programming outside python (e.g. in bash). Additionally, in https://docs.python.org/3/using/cmdline.html is clearly stated that "_default search path is installation dependent_". – ilias iliadis Mar 23 '18 at 07:54
16

Inside a package if there is setup.py, then better to install it

pip install -e .
Nagashayan
  • 2,487
  • 2
  • 18
  • 22
6

A simple way to make it work is to run your script from the parent directory using python's -m flag, e.g. python -m packagename.scriptname. Obviously in this situation you need an __init__.py file to turn your directory into a package.

bradley.ayers
  • 37,165
  • 14
  • 93
  • 99
5

A bit late to the party, but this is what worked for me:

>>> import sys
>>> sys.path.insert(0, '')

Apparently, if there is an empty string, Python knows that it should look in the current directory. I did not have the empty string in sys.path, which caused this error.

4

Using sys.path should include current directory already.

Try:

import .

or:

from . import sth

however it may be not a good practice, so why not just use:

import mypackage
kenorb
  • 155,785
  • 88
  • 678
  • 743
sunqiang
  • 6,422
  • 1
  • 32
  • 32
  • 6
    Problem with is that it will load the package from the global python env, it might load the package/file from the local folder, but it could just as well load some other random mypackge that is in the working env. – JAR.JAR.beans Jun 07 '16 at 12:44
0

Speaking for python3.. I wanted to use an improved version of a library that's installed in my environment. There are some extra print statements it makes to show that it and not the original lib is being used.

I placed the lib's folder next to the python script. Ran the script.. it ran with the local lib with the modifications.

Removed the folder and ran it again - this time it ran with the installed lib.

So, solution was simple : place the lib's folder (with same name as in your import statement) in your project folder. That does the job, at least at my end.

This is on a standard Linux Mint 20.04 system, with a python 3.8 virutal environment activated (so "(py3.8)" appears in my terminal when I'm in the virtual env)

Nikhil VJ
  • 5,630
  • 7
  • 34
  • 55
0

You can import package_name if the package is a module: this needs you have init.py under the package and things that you want to use are needed to import in the init.py

Or if you want to import class under the package, you can use from package_name import class_name

htlbydgod
  • 330
  • 2
  • 8