Меню

Ошибка при импорте модуля python

In my case, it is permission problem. The package was somehow installed with root rw permission only, other user just cannot rw to it!

nbro's user avatar

nbro

14.7k29 gold badges107 silver badges192 bronze badges

answered May 4, 2013 at 17:55

Paul Wang's user avatar

Paul WangPaul Wang

1,6361 gold badge12 silver badges19 bronze badges

7

I had the same problem: script with import colorama was throwing and ImportError, but sudo pip install colorama was telling me «package already installed».

My fix: run pip without sudo: pip install colorama. Then pip agreed it needed to be installed, installed it, and my script ran.

My environment is Ubuntu 14.04 32-bit; I think I saw this before and after I activated my virtualenv.

UPDATE: even better, use python -m pip install <package>. The benefit of this is, since you are executing the specific version of python that you want the package in, pip will unequivocally install the package in to the «right» python. Again, don’t use sudo in this case… then you get the package in the right place, but possibly with (unwanted) root permissions.

answered Jan 14, 2016 at 19:12

Dan H's user avatar

Dan HDan H

13.6k6 gold badges38 silver badges32 bronze badges

3

It’s the python path problem.

In my case, I have python installed in:

/Library/Frameworks/Python.framework/Versions/2.6/bin/python,

and there is no site-packages directory within the python2.6.

The package(SOAPpy) I installed by pip is located

/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/

And site-package is not in the python path, all I did is add site-packages to PYTHONPATH permanently.

  1. Open up Terminal

  2. Type open .bash_profile

  3. In the text file that pops up, add this line at the end:

    export PYTHONPATH=$PYTHONPATH:/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
    
  4. Save the file, restart the Terminal, and you’re done

desertnaut's user avatar

desertnaut

55.9k21 gold badges133 silver badges163 bronze badges

answered Apr 22, 2014 at 17:45

user1552891's user avatar

user1552891user1552891

5095 silver badges4 bronze badges

3

I was able to correct this issue with a combined approach. First, I followed Chris’ advice, opened a command line and typed ‘pip show packagename’
This provided the location of the installed package.

Next, I opened python and typed ‘import sys’, then ‘sys.path’ to show where my python searches for any packages I import. Alas, the location shown in the first step was NOT in the list.

Final step, I typed ‘sys.path.append(‘package_location_seen_in_step_1’). You optionally can repeat step two to see the location is now in the list.

Test step, try to import the package again… it works.

The downside? It is temporary, and you need to add it to the list each time.

answered Apr 1, 2018 at 20:19

MJ_'s user avatar

MJ_MJ_

5141 gold badge5 silver badges10 bronze badges

The Python import mechanism works, really, so, either:

  1. Your PYTHONPATH is wrong,
  2. Your library is not installed where you think it is
  3. You have another library with the same name masking this one

answered Jan 12, 2013 at 17:19

Ali Afshar's user avatar

Ali AfsharAli Afshar

40.5k12 gold badges93 silver badges109 bronze badges

8

I have been banging my head against my monitor on this until a young-hip intern told me the secret is to «python setup.py install» inside the module directory.

For some reason, running the setup from there makes it just work.

To be clear, if your module’s name is «foo»:

[burnc7 (2016-06-21 15:28:49) git]# ls -l
total 1
drwxr-xr-x 7 root root  118 Jun 21 15:22 foo
[burnc7 (2016-06-21 15:28:51) git]# cd foo
[burnc7 (2016-06-21 15:28:53) foo]# ls -l
total 2
drwxr-xr-x 2 root root   93 Jun 21 15:23 foo
-rw-r--r-- 1 root root  416 May 31 12:26 setup.py
[burnc7 (2016-06-21 15:28:54) foo]# python setup.py install
<--snip-->

If you try to run setup.py from any other directory by calling out its path, you end up with a borked install.

DOES NOT WORK:

python /root/foo/setup.py install

DOES WORK:

cd /root/foo
python setup.py install

answered Jun 21, 2016 at 22:32

Locane's user avatar

LocaneLocane

2,7662 gold badges22 silver badges33 bronze badges

I encountered this while trying to use keyring which I installed via sudo pip install keyring. As mentioned in the other answers, it’s a permissions issue in my case.

What worked for me:

  1. Uninstalled keyring:
  • sudo pip uninstall keyring
  1. I used sudo’s -H option and reinstalled keyring:
  • sudo -H pip install keyring

bad_coder's user avatar

bad_coder

10.3k20 gold badges43 silver badges65 bronze badges

answered Sep 4, 2018 at 5:56

blackleg's user avatar

blacklegblackleg

3513 silver badges3 bronze badges

In PyCharm, I fixed this issue by changing the project interpreter path.

File -> Settings -> Project -> Project Interpreter

File -> Invalidate Caches… may be required afterwards.

miken32's user avatar

miken32

41k16 gold badges105 silver badges148 bronze badges

answered Feb 27, 2019 at 18:40

Amit D's user avatar

Amit DAmit D

611 silver badge2 bronze badges

1

I couldn’t get my PYTHONPATH to work properly. I realized adding export fixed the issue:

(did work)

export PYTHONPATH=$PYTHONPATH:~/test/site-packages

vs.

(did not work)

PYTHONPATH=$PYTHONPATH:~/test/site-packages

buczek's user avatar

buczek

2,0097 gold badges28 silver badges39 bronze badges

answered Dec 6, 2016 at 16:32

George Weber's user avatar

This problem can also occur with a relocated virtual environment (venv).

I had a project with a venv set up inside the root directory. Later I created a new user and decided to move the project to this user. Instead of moving only the source files and installing the dependencies freshly, I moved the entire project along with the venv folder to the new user.

After that, the dependencies that I installed were getting added to the global site-packages folder instead of the one inside the venv, so the code running inside this env was not able to access those dependencies.

To solve this problem, just remove the venv folder and recreate it again, like so:

$ deactivate
$ rm -rf venv
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt

Karl Knechtel's user avatar

Karl Knechtel

60.6k11 gold badges93 silver badges138 bronze badges

answered Nov 24, 2020 at 5:34

Jaikishan's user avatar

1

Something that worked for me was:

python -m pip install -user {package name}

The command does not require sudo. This was tested on OSX Mojave.

answered Aug 19, 2019 at 21:35

IShaan's user avatar

IShaanIShaan

831 gold badge1 silver badge6 bronze badges

0

In my case I had run pip install Django==1.11 and it would not import from the python interpreter.

Browsing through pip’s commands I found pip show which looked like this:

> pip show Django
Name: Django
Version: 1.11
...
Location: /usr/lib/python3.4/site-packages
...

Notice the location says ‘3.4’. I found that the python-command was linked to python2.7

/usr/bin> ls -l python
lrwxrwxrwx 1 root root 9 Mar 14 15:48 python -> python2.7

Right next to that I found a link called python3 so I used that. You could also change the link to python3.4. That would fix it, too.

answered Apr 6, 2017 at 14:05

Chris's user avatar

ChrisChris

5,4204 gold badges29 silver badges39 bronze badges

In my case it was a problem with a missing init.py file in the module, that I wanted to import in a Python 2.7 environment.

Python 3.3+ has Implicit Namespace Packages that allow it to create a packages without an init.py file.

answered Apr 26, 2019 at 9:26

jens_laufer's user avatar

jens_lauferjens_laufer

1572 silver badges10 bronze badges

Had this problem too.. the package was installed on Python 3.8.0 but VS Code was running my script using an older version (3.4)

fix in terminal:

py .py

Make sure you’re installing the package on the right Python Version

answered Nov 21, 2019 at 20:39

Aramich100's user avatar

I had colorama installed via pip and I was getting «ImportError: No module named colorama»

So I searched with «find», found the absolute path and added it in the script like this:

import sys
sys.path.append("/usr/local/lib/python3.8/dist-packages/")
import colorama 

And it worked.

answered Aug 25, 2020 at 13:01

DimiDak's user avatar

DimiDakDimiDak

4,3782 gold badges23 silver badges31 bronze badges

I had just the same problem, and updating setuptools helped:

python3 -m pip install --upgrade pip setuptools wheel

After that, reinstall the package, and it should work fine 🙂

The thing is, the package is built incorrectly if setuptools is old.

answered Jul 28, 2022 at 8:00

Ivan Konovalov's user avatar

If the other answers mentioned do not work for you, try deleting your pip cache and reinstalling the package. My machine runs Ubuntu14.04 and it was located under ~/.cache/pip. Deleting this folder did the trick for me.

answered Aug 7, 2019 at 1:29

Scrotch's user avatar

ScrotchScrotch

1,2561 gold badge15 silver badges25 bronze badges

Also, make sure that you do not confuse pip3 with pip. What I found was that package installed with pip was not working with python3 and vice-versa.

answered Nov 14, 2019 at 14:14

Devansh Maurya's user avatar

I had similar problem (on Windows) and the root cause in my case was ANTIVIRUS software! It has «Auto-Containment» feature, that wraps running process with some kind of a virtual machine.
Symptoms are: pip install somemodule works fine in one cmd-line window and import somemodule fails when executed from another process with the error

ModuleNotFoundError: No module named 'somemodule'

bad_coder's user avatar

bad_coder

10.3k20 gold badges43 silver badges65 bronze badges

answered May 7, 2018 at 6:42

Dima G's user avatar

Dima GDima G

1,82516 silver badges22 bronze badges

In my case (an Ubuntu 20.04 VM on WIN10 Host), I have a disordered situation with many version of Python installed and variuos point of Shared Library (installed with pip in many points of the File System). I’m referring to 3.8.10 Python version.
After many tests, I’ve found a suggestion searching with google (but’ I’m sorry, I haven’t the link). This is what I’ve done to resolve the problem :

  1. From shell session on Ubuntu 20.04 VM, (inside the Home, in my case /home/hduser), I’ve started a Jupyter Notebook session with the command «jupyter notebook».

  2. Then, when jupyter was running I’ve opened a .ipynb file to give commands.

  3. First : pip list —> give me the list of packages installed, and, sympy
    wasn’t present (although I had installed it with «sudo pip install sympy»
    command.

  4. Last with the command !pip3 install sympy (inside jupyter notebook
    session) I’ve solved the problem, here the screen-shot :
    enter image description here

  5. Now, with !pip list the package «sympy» is present, and working :
    enter image description here

answered Jan 9, 2022 at 11:43

Colonna Maurizio's user avatar

In my case, I assumed a package was installed because it showed up in the output of pip freeze. However, just the site-packages/*.dist-info folder is enough for pip to list it as installed despite missing the actual package contents (perhaps from an accidental deletion). This happens even when all the path settings are correct, and if you try pip install <pkg> it will say «requirement already satisfied».

The solution is to manually remove the dist-info folder so that pip realizes the package contents are missing. Then, doing a fresh install should re-populate anything that was accidentally removed

answered Oct 4, 2022 at 17:59

Addison Klinke's user avatar

Addison KlinkeAddison Klinke

9172 gold badges11 silver badges23 bronze badges

When you install via easy_install or pip, is it completing successfully? What is the full output? Which python installation are you using? You may need to use sudo before your installation command, if you are installing modules to a system directory (if you are using the system python installation, perhaps). There’s not a lot of useful information in your question to go off of, but some tools that will probably help include:

  • echo $PYTHONPATH and/or echo $PATH: when importing modules, Python searches one of these environment variables (lists of directories, : delimited) for the module you want. Importing problems are often due to the right directory being absent from these lists

  • which python, which pip, or which easy_install: these will tell you the location of each executable. It may help to know.

  • Use virtualenv, like @JesseBriggs suggests. It works very well with pip to help you isolate and manage the modules and environment for separate Python projects.

answered Jan 12, 2013 at 17:26

Ryan Artecona's user avatar

Ryan ArteconaRyan Artecona

5,8453 gold badges18 silver badges18 bronze badges

0

I had this exact problem, but none of the answers above worked. It drove me crazy until I noticed that sys.path was different after I had imported from the parent project. It turned out that I had used importlib to write a little function in order to import a file not in the project hierarchy. Bad idea: I forgot that I had done this. Even worse, the import process mucked with the sys.path—and left it that way. Very bad idea.

The solution was to stop that, and simply put the file I needed to import into the project. Another approach would have been to put the file into its own project, as it needs to be rebuilt from time to time, and the rebuild may or may not coincide with the rebuild of the main project.

answered Apr 17, 2016 at 19:08

ivanlan's user avatar

ivanlanivanlan

9596 silver badges8 bronze badges

I had this problem with 2.7 and 3.5 installed on my system trying to test a telegram bot with Python-Telegram-Bot.

I couldn’t get it to work after installing with pip and pip3, with sudo or without. I always got:

Traceback (most recent call last):
  File "telegram.py", line 2, in <module>
    from telegram.ext import Updater
  File "$USER/telegram.py", line 2, in <module>
    from telegram.ext import Updater
ImportError: No module named 'telegram.ext'; 'telegram' is not a package

Reading the error message correctly tells me that python is looking in the current directory for a telegram.py. And right, I had a script lying there called telegram.py and this was loaded by python when I called import.

Conclusion, make sure you don’t have any package.py in your current working dir when trying to import. (And read error message thoroughly).

answered Jan 10, 2017 at 7:09

Patrick B.'s user avatar

Patrick B.Patrick B.

11.5k8 gold badges58 silver badges98 bronze badges

I had a similar problem using Django. In my case, I could import the module from the Django shell, but not from a .py which imported the module.
The problem was that I was running the Django server (therefore, executing the .py) from a different virtualenv from which the module had been installed.

Instead, the shell instance was being run in the correct virtualenv. Hence, why it worked.

mx0's user avatar

mx0

6,10711 gold badges51 silver badges53 bronze badges

answered May 9, 2019 at 17:41

aleclara95's user avatar

This Works!!!

This often happens when module is installed to an older version of python or another directory, no worries as solution is simple.
— import module from directory in which module is installed.
You can do this by first importing the python sys module then importing from the path in which the module is installed

import sys
sys.path.append("directory in which module is installed")

import <module_name>

answered Jul 4, 2019 at 1:56

Terrence_Freeman's user avatar

Most of the possible cases have been already covered in solutions, just sharing my case, it happened to me that I installed a package in one environment (e.g. X) and I was importing the package in another environment (e.g. Y). So, always make sure that you’re importing the package from the environment in which you installed the package.

answered Aug 2, 2019 at 16:45

Pedram's user avatar

PedramPedram

2,3362 gold badges29 silver badges45 bronze badges

For me it was ensuring the version of the module aligned with the version of Python I was using.. I built the image on a box with Python 3.6 and then injected into a Docker image that happened to have 3.7 installed, and then banging my head when Python was telling me the module wasn’t installed…

36m for Python 3.6
bsonnumpy.cpython-36m-x86_64-linux-gnu.so

37m for Python 3.7 bsonnumpy.cpython-37m-x86_64-linux-gnu.so

answered Sep 18, 2019 at 15:43

mkst's user avatar

mkstmkst

5546 silver badges16 bronze badges

4

I know this is a super old post but for me, I had an issue with a 32 bit python and 64 bit python installed. Once I uninstalled the 32 bit python, everything worked as it should.

answered Sep 24, 2019 at 13:18

Moultrie's user avatar

I have solved my issue that same libraries were working fine in one project(A) but importing those same libraries in another project(B) caused error. I am using Pycharm as IDE at Windows OS.
So, after trying many potential solutions and failing to solve the issue, I did these two things (deleted «Venv» folder, and reconfigured interpreter):

1-In project(B), there was a folder named(«venv»), located in External Libraries/. I deleted that folder.

2-Step 1 (deleting «venv» folder) causes error in Python Interpreter Configuration, and
there is a message shown at top of screen saying «Invalid python interpreter selected
for the project» and «configure python interpreter», select that link and it opens a
new window. There in «Project Interpreter» drop-down list, there is a Red colored line
showing previous invalid interpreter. Now, Open this list and select the Python
Interpreter(in my case, it is Python 3.7). Press «Apply» and «OK» at the bottom and you
are good to go.

Note: It was potentially the issue where Virtual Environment of my Project(B) was not recognizing the already installed and working libraries.

answered Sep 29, 2019 at 12:06

Hasnain Haider's user avatar

I have a specific problem which might require a general solution. I am currently learning apache thrift. I used this guide.I followed all the steps and i am getting a import error as Cannot import module UserManager. So the question being
How does python import lookup take place. Which directory is checked first. How does it move upwards?
How does sys.path.append(») work?

I found out the answer for this here. I followed the same steps. But i am still facing the same issue. Any ideas why? Anything more i should put up that could help debug you guys. ?

Help is appreciated.

asked May 26, 2015 at 10:34

Saras Arya's user avatar

Saras AryaSaras Arya

2,8728 gold badges38 silver badges69 bronze badges

0

On windows, Python looks up modules from the Lib folder in the default python path, for example from «C:Python34Lib». You can add your Python libaries in a custom folder («my-lib» or sth.) in there, but you need a file in order to tell Python that you can import from there. This file is called __init__.py , and is totally empty. That data structure should look like this:

my-lib

  • __init__.py
  • /myfolder
  • mymodule.py

    (This is how every Python module works. For example urllib.request, it’s at «%PYTHONPATH%Liburllibrequest.py»)

    You can import from the «mymodule.py» file by typing

    import my-lib
    

    and then using

    mylib.mymodule.myfunction
    

    or you can use

    from my-lib import mymodule
    

    And then just using the name of you function.

    You can now use sys.path.append to append the path you pass into the function to the folders Python looks for the modules (Please note that thats not permanent). If the path of your modules should be static, you should consider putting these in the Lib folder. If that path is relative to your file you could look for the path of the file you execute from, and then append the sys.path relative to your file, but i reccomend using relative imports.

    If you consider doing that, i recommend reading the docs, you can do that here: https://docs.python.org/3/reference/import.html#submodules

  • answered May 26, 2015 at 15:28

    Agilix's user avatar

    AgilixAgilix

    3041 silver badge13 bronze badges

    2

    If I got you right, you’re using Python 3.3 from Blender but try to include the 3.2 standard library. This is bound to give you a flurry of issues, you should not do that. Find another way. It’s likely that Blender offers a way to use the 3.3 standard library (and that’s 99% compatible with 3.2). Pure-Python third party library can, of course, be included by fiddling with sys.path.

    The specific issue you’re seeing now is likely caused by the version difference. As people have pointed out in the comments, Python 3.3 doesn’t find the _tkinter extension module. Although it is present (as it works from Python 3.2), it is most likely in a .so file with an ABI tag that is incompatible with Blender’s Python 3.3, hence it won’t even look at it (much like a module.txt is not considered for import module). This is a good thing. Extension modules are highly version-specific, slight ABI mismatches (such as between 3.2 and 3.3, or two 3.3 compiled with different options) can cause pretty much any kind of error, from crashes to memory leaks to silent data corruption or even something completely different.

    You can verify whether this is the case via import _tkinter; print(_tkinter.file) in the 3.2 shell. Alternatively, _tkinter may live in a different directory entirely. Adding that directory won’t actually fix the real issue outlined above.

    answered May 26, 2015 at 10:40

    Ravinther M's user avatar

    Ravinther MRavinther M

    2632 silver badges13 bronze badges

    For any new readers coming along that are still having issues, try the following. This is cleaner than using sys.path.append if your app directory is structured with your .py files that contain functions for import underneath your script that imports those files. Let me illustrate.

    Script that imports files: main.py

    Function files named like: func1.py

    main.py
       /functionfolder
          __init__.py
          func1.py
          func2.py
    

    The import code in your main.py file should look as follows:

    from functionfolder import func1
    from functionfolder import func2
    

    As Agilix correctly stated, you must have an __init__.py file in your «functionfolder» (see directory illustration above).

    In addition, this solved my issue with Pylance not resolving the import, and showing me a nagging error constantly. After a rabbit-hole of sifting through GitHub issues, and trying too many comparatively complicated proposed solutions, this ever-so-simple solution worked for me.

    answered Apr 13, 2021 at 1:34

    Sean Richards's user avatar

    You may try with declaring sys.path.append(‘/path/to/lib/python’) before including any IMPORT statements.

    answered May 26, 2015 at 10:40

    Pralhad Narsinh Sonar's user avatar

    I just created a __init__.py file inside my new folder, so the directory is initialised, and it worked (:

    answered Feb 1, 2022 at 13:10

    Luis's user avatar

    1

    I have a specific problem which might require a general solution. I am currently learning apache thrift. I used this guide.I followed all the steps and i am getting a import error as Cannot import module UserManager. So the question being
    How does python import lookup take place. Which directory is checked first. How does it move upwards?
    How does sys.path.append(») work?

    I found out the answer for this here. I followed the same steps. But i am still facing the same issue. Any ideas why? Anything more i should put up that could help debug you guys. ?

    Help is appreciated.

    asked May 26, 2015 at 10:34

    Saras Arya's user avatar

    Saras AryaSaras Arya

    2,8728 gold badges38 silver badges69 bronze badges

    0

    On windows, Python looks up modules from the Lib folder in the default python path, for example from «C:Python34Lib». You can add your Python libaries in a custom folder («my-lib» or sth.) in there, but you need a file in order to tell Python that you can import from there. This file is called __init__.py , and is totally empty. That data structure should look like this:

    my-lib

  • __init__.py
  • /myfolder
  • mymodule.py

    (This is how every Python module works. For example urllib.request, it’s at «%PYTHONPATH%Liburllibrequest.py»)

    You can import from the «mymodule.py» file by typing

    import my-lib
    

    and then using

    mylib.mymodule.myfunction
    

    or you can use

    from my-lib import mymodule
    

    And then just using the name of you function.

    You can now use sys.path.append to append the path you pass into the function to the folders Python looks for the modules (Please note that thats not permanent). If the path of your modules should be static, you should consider putting these in the Lib folder. If that path is relative to your file you could look for the path of the file you execute from, and then append the sys.path relative to your file, but i reccomend using relative imports.

    If you consider doing that, i recommend reading the docs, you can do that here: https://docs.python.org/3/reference/import.html#submodules

  • answered May 26, 2015 at 15:28

    Agilix's user avatar

    AgilixAgilix

    3041 silver badge13 bronze badges

    2

    If I got you right, you’re using Python 3.3 from Blender but try to include the 3.2 standard library. This is bound to give you a flurry of issues, you should not do that. Find another way. It’s likely that Blender offers a way to use the 3.3 standard library (and that’s 99% compatible with 3.2). Pure-Python third party library can, of course, be included by fiddling with sys.path.

    The specific issue you’re seeing now is likely caused by the version difference. As people have pointed out in the comments, Python 3.3 doesn’t find the _tkinter extension module. Although it is present (as it works from Python 3.2), it is most likely in a .so file with an ABI tag that is incompatible with Blender’s Python 3.3, hence it won’t even look at it (much like a module.txt is not considered for import module). This is a good thing. Extension modules are highly version-specific, slight ABI mismatches (such as between 3.2 and 3.3, or two 3.3 compiled with different options) can cause pretty much any kind of error, from crashes to memory leaks to silent data corruption or even something completely different.

    You can verify whether this is the case via import _tkinter; print(_tkinter.file) in the 3.2 shell. Alternatively, _tkinter may live in a different directory entirely. Adding that directory won’t actually fix the real issue outlined above.

    answered May 26, 2015 at 10:40

    Ravinther M's user avatar

    Ravinther MRavinther M

    2632 silver badges13 bronze badges

    For any new readers coming along that are still having issues, try the following. This is cleaner than using sys.path.append if your app directory is structured with your .py files that contain functions for import underneath your script that imports those files. Let me illustrate.

    Script that imports files: main.py

    Function files named like: func1.py

    main.py
       /functionfolder
          __init__.py
          func1.py
          func2.py
    

    The import code in your main.py file should look as follows:

    from functionfolder import func1
    from functionfolder import func2
    

    As Agilix correctly stated, you must have an __init__.py file in your «functionfolder» (see directory illustration above).

    In addition, this solved my issue with Pylance not resolving the import, and showing me a nagging error constantly. After a rabbit-hole of sifting through GitHub issues, and trying too many comparatively complicated proposed solutions, this ever-so-simple solution worked for me.

    answered Apr 13, 2021 at 1:34

    Sean Richards's user avatar

    You may try with declaring sys.path.append(‘/path/to/lib/python’) before including any IMPORT statements.

    answered May 26, 2015 at 10:40

    Pralhad Narsinh Sonar's user avatar

    I just created a __init__.py file inside my new folder, so the directory is initialised, and it worked (:

    answered Feb 1, 2022 at 13:10

    Luis's user avatar

    1

    ModuleNotFoundError: no module named Python Error [Fixed]

    When you try to import a module in a Python file, Python tries to resolve this module in several ways. Sometimes, Python throws the ModuleNotFoundError afterward. What does this error mean in Python?

    As the name implies, this error occurs when you’re trying to access or use a module that cannot be found. In the case of the title, the «module named Python» cannot be found.

    Python here can be any module. Here’s an error when I try to import a numpys module that cannot be found:

    import numpys as np
    

    Here’s what the error looks like:

    image-341

    Here are a few reasons why a module may not be found:

    • you do not have the module you tried importing installed on your computer
    • you spelled a module incorrectly (which still links back to the previous point, that the misspelled module is not installed)…for example, spelling numpy as numpys during import
    • you use an incorrect casing for a module (which still links back to the first point)…for example, spelling numpy as NumPy during import will throw the module not found error as both modules are «not the same»
    • you are importing a module using the wrong path

    How to fix the ModuleNotFoundError in Python

    As I mentioned in the previous section, there are a couple of reasons a module may not be found. Here are some solutions.

    1. Make sure imported modules are installed

    Take for example, numpy. You use this module in your code in a file called «test.py» like this:

    import numpy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    If you try to run this code with python test.py and you get this error:

    ModuleNotFoundError: No module named "numpy"
    

    Then it’s most likely possible that the numpy module is not installed on your device. You can install the module like this:

    python -m pip install numpy
    

    When installed, the previous code will work correctly and you get the result printed in your terminal:

    [1, 2, 3]
    

    2. Make sure modules are spelled correctly

    In some cases, you may have installed the module you need, but trying to use it still throws the ModuleNotFound error. In such cases, it could be that you spelled it incorrectly. Take, for example, this code:

    import nompy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    Here, you have installed numpy but running the above code throws this error:

    ModuleNotFoundError: No module named "nompy"
    

    This error comes as a result of the misspelled numpy module as nompy (with the letter o instead of u). You can fix this error by spelling the module correctly.

    3. Make sure modules are in the right casing

    Similar to the misspelling issue for module not found errors, it could also be that you are spelling the module correctly, but in the wrong casing. Here’s an example:

    import Numpy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    For this code, you have numpy installed but running the above code will throw this error:

    ModuleNotFoundError: No module named 'Numpy'
    

    Due to casing differences, numpy and Numpy are different modules. You can fix this error by spelling the module in the right casing.

    4. Make sure you use the right paths

    In Python, you can import modules from other files using absolute or relative paths. For this example, I’ll focus on absolute paths.

    When you try to access a module from the wrong path, you will also get the module not found here. Here’s an example:

    Let’s say you have a project folder called test. In it, you have two folders demoA and demoB.

    demoA has an __init__.py file (to show it’s a Python package) and a test1.py module.

    demoA also has an __init__.py file and a test2.py module.

    Here’s the structure:

    └── test
        ├── demoA
            ├── __init__.py
        │   ├── test1.py
        └── demoB
            ├── __init__.py
            ├── test2.py
    

    Here are the contents of test1.py:

    def hello():
      print("hello")
    

    And let’s say you want to use this declared hello function in test2.py. The following code will throw a module not found error:

    import demoA.test as test1
    
    test1.hello()
    

    This code will throw the following error:

    ModuleNotFoundError: No module named 'demoA.test'
    

    The reason for this is that we have used the wrong path to access the test1 module. The right path should be demoA.test1. When you correct that, the code works:

    import demoA.test1 as test1
    
    test1.hello()
    # hello
    

    Wrapping up

    For resolving an imported module, Python checks places like the inbuilt library, installed modules, and modules in the current project. If it’s unable to resolve that module, it throws the ModuleNotFoundError.

    Sometimes you do not have that module installed, so you have to install it. Sometimes it’s a misspelled module, or the naming with the wrong casing, or a wrong path. In this article, I’ve shown four possible ways of fixing this error if you experience it.

    I hope you learned from it 🙂



    Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

    В Python может быть несколько причин возникновения ошибки ModuleNotFoundError: No module named ...:

    • Модуль Python не установлен.
    • Есть конфликт в названиях пакета и модуля.
    • Есть конфликт зависимости модулей Python.

    Рассмотрим варианты их решения.

    Модуль не установлен

    В первую очередь нужно проверить, установлен ли модуль. Для использования модуля в программе его нужно установить. Например, если попробовать использовать numpy без установки с помощью pip install будет следующая ошибка:

    Traceback (most recent call last):
       File "", line 1, in 
     ModuleNotFoundError: No module named 'numpy'

    Для установки нужного модуля используйте следующую команду:

    pip install numpy
    # или
    pip3 install numpy

    Или вот эту если используете Anaconda:

    conda install numpy

    Учтите, что может быть несколько экземпляров Python (или виртуальных сред) в системе. Модуль нужно устанавливать в определенный экземпляр.

    Конфликт имен библиотеки и модуля

    Еще одна причина ошибки No module named — конфликт в названиях пакета и модуля. Предположим, есть следующая структура проекта Python:

    demo-project
     └───utils
             __init__.py
             string_utils.py
             utils.py

    Если использовать следующую инструкцию импорта файла utils.py, то Python вернет ошибку ModuleNotFoundError.


    >>> import utils.string_utils
    Traceback (most recent call last):
    File "C:demo-projectutilsutils.py", line 1, in
    import utils.string_utils
    ModuleNotFoundError: No module named 'utils.string_utils';
    'utils' is not a package

    В сообщении об ошибке сказано, что «utils is not a package». utils — это имя пакета, но это также и имя модуля. Это приводит к конфликту, когда имя модуля перекрывает имя пакета/библиотеки. Для его разрешения нужно переименовать файл utils.py.

    Иногда может существовать конфликт модулей Python, который и приводит к ошибке No module named.

    Следующее сообщение явно указывает, что _numpy_compat.py в библиотеке scipy пытается импортировать модуль numpy.testing.nosetester.

    Traceback (most recent call last):
       File "C:demo-projectvenv
    Libsite-packages
             scipy_lib_numpy_compat.py", line 10, in
         from numpy.testing.nosetester import import_nose
     ModuleNotFoundError: No module named 'numpy.testing.nosetester'

    Ошибка ModuleNotFoundError возникает из-за того, что модуль numpy.testing.nosetester удален из библиотеки в версии 1.18. Для решения этой проблемы нужно обновить numpy и scipy до последних версий.

    pip install numpy --upgrade
    pip install scipy --upgrade 

    Что означает ошибка ModuleNotFoundError: No module named

    Что означает ошибка ModuleNotFoundError: No module named

    Python ругается, что не может найти нужный модуль

    Python ругается, что не может найти нужный модуль

    Ситуация: мы решили заняться бигдатой и обработать большой массив данных на Python. Чтобы было проще, мы используем уже готовые решения и находим нужный нам код в интернете, например такой:

    import numpy as np
    x = [2, 3, 4, 5, 6]
    nums = np.array([2, 3, 4, 5, 6])
    type(nums)
    zeros = np.zeros((5, 4))
    lin = np.linspace(1, 10, 20)

    Копируем, вставляем в редактор кода и запускаем, чтобы разобраться, как что работает. Но вместо обработки данных Python выдаёт ошибку:

    ❌ModuleNotFoundError: No module named numpy

    Странно, но этот код точно правильный: мы его взяли из блога разработчика и, по комментариям, у всех всё работает. Откуда тогда ошибка?

    Что это значит: Python пытается подключить библиотеку, которую мы указали, но не может её найти у себя.

    Когда встречается: когда библиотеки нет или мы неправильно написали её название.

    Что делать с ошибкой ModuleNotFoundError: No module named

    Самый простой способ исправить эту ошибку — установить библиотеку, которую мы хотим подключить в проект. Для установки Python-библиотек используют штатную команду pip или pip3, которая работает так: pip install <имя_библиотеки>. В нашем случае Python говорит, что он не может подключить библиотеку Numpy, поэтому пишем в командной строке такое:

    pip install numpy

    Это нужно написать не в командной строке Python, а в командной строке операционной системы. Тогда компьютер скачает эту библиотеку, установит, привяжет к Python и будет ругаться на строчку в коде import numpy.

    Ещё бывает такое, что библиотека называется иначе, чем указано в команде pip install. Например, для работы с телеграм-ботами нужна библиотека telebot, а для её установки надо написать pip install pytelegrambotapi. Если попробовать подключить библиотеку с этим же названием, то тоже получим ошибку:

    Что означает ошибка ModuleNotFoundError: No module named

    А иногда такая ошибка — это просто невнимательность: пропущенная буква в названии библиотеки или опечатка. Исправляем и работаем дальше.

    Вёрстка:

    Кирилл Климентьев

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    from tkinter import *
    import numpy as np
    import random
     
    canvas_width = 700
    canvas_height = 500
    brush_size = 3
    color = "black"
     
    def create_point():
        chislo = message.get()
        n = int(chislo) - 1
        x1 = random.randrange(start=1, stop=700)
        y1 = random.randrange(start=1, stop=500)
        for i in range(n):
            x2 = random.randrange(start=1, stop=700)
            y2 = random.randrange(start=1, stop=500)
            w.create_line(x1, y1, x2, y2, fill=color)
            x1 = x2
            y1 = y2
     
    root = Tk()
    root.title("Точки-ломаная-сгладить")
     
    message = StringVar()
     
    message_entry = Entry(textvariable=message)
     
    w = Canvas(root, width=canvas_width, height=canvas_height, bg="white")
    w.bind("<B1-Motion>")
     
    create_btn = Button(text="Соединить точки", width=14, command=lambda: create_point())
    b_btn = Button(text="Сгладить ломаную", width=15, command=lambda: color_change("yellow"))
    clear_btn = Button(text="Очистить", width=10, command=lambda: w.delete("all"))
     
    w.grid(row=2, column=0, columnspan=7, padx=5, pady=5, sticky=E+W+S+N)
    w.columnconfigure(6, weight=1)
    w.rowconfigure(2, weight=1)
     
    message_entry.grid(row=0, column=2)
    create_btn.grid(row=0, column=3)
    b_btn.grid(row=0, column=4)
    clear_btn.grid(row=0, column=5, sticky=W)
     
    root.mainloop()

    Порой бывает трудно правильно реализовать import с первого раза, особенно если мы хотим добиться правильной работы на плохо совместимых между собой версиях Python 2 и Python 3. Попытаемся разобраться, что из себя представляют импорты в Python и как написать решение, которое подойдёт под обе версии языка.

    Содержание

    • Ключевые моменты
    • Основные определения
    • Пример структуры директорий
    • Что делает import
    • Основы import и sys.path
    • Чуть подробнее о sys.path
    • Всё о __init__.py
    • Использование объектов из импортированного модуля или пакета
    • Используем dir() для исследования содержимого импортированного модуля
    • Импортирование пакетов
    • Абсолютный и относительный импорт
    • Примеры
    • Python 2 vs Python 3
    • Прочие темы, не рассмотренные здесь, но достойные упоминания

    Ключевые моменты

    • Выражения import производят поиск по списку путей в sys.path.
    • sys.path всегда включает в себя путь скрипта, запущенного из командной строки, и не зависит от текущей рабочей директории.
    • Импортирование пакета по сути равноценно импортированию  __init__.py этого пакета.

    Основные определения

    • Модуль: любой файл *.py. Имя модуля — имя этого файла.
    • Встроенный модуль: «модуль», который был написан на Си, скомпилирован и встроен в интерпретатор Python, и потому не имеет файла *.py.
    • Пакет: любая папка, которая содержит файл __init__.py. Имя пакета — имя папки.
      • С версии Python 3.3 любая папка (даже без __init__.py) считается пакетом.
    • Объект: в Python почти всё является объектом — функции, классы, переменные и т. д.

    Пример структуры директорий

    test/                      # Корневая папка
        packA/                 # Пакет packA
            subA/              # Подпакет subA
                __init__.py
                sa1.py
                sa2.py
            __init__.py
            a1.py
            a2.py
        packB/                 # Пакет packB (неявный пакет пространства имён)
            b1.py
            b2.py
        math.py
        random.py
        other.py
        start.py

    Обратите внимание, что в корневой папке test/ нет файла __init__.py.

    Что делает import

    При импорте модуля Python выполняет весь код в нём. При импорте пакета Python выполняет код в файле пакета __init__.py, если такой имеется. Все объекты, определённые в модуле или __init__.py, становятся доступны импортирующему.

    Основы import и sys.path

    Вот как оператор import производит поиск нужного модуля или пакета согласно документации Python:

    При импорте модуля spam интерпретатор сначала ищёт встроенный модуль с таким именем. Если такого модуля нет, то идёт поиск файла spam.py в списке директорий, определённых в переменной sys.path. sys.path инициализируется из следующих мест:

    • директории, содержащей исходный скрипт (или текущей директории, если файл не указан);
    • директории по умолчанию, которая зависит от дистрибутива Python;
    • PYTHONPATH (список имён директорий; имеет синтаксис, аналогичный переменной окружения PATH).

    Программы могут изменять переменную sys.path после её инициализации. Директория, содержащая запускаемый скрипт, помещается в начало поиска перед путём к стандартной библиотеке. Это значит, что скрипты в этой директории будут импортированы вместо модулей с такими же именами в стандартной библиотеке.

    Источник: Python 2 и Python 3

    Технически документация не совсем полна. Интерпретатор будет искать не только файл (модуль) spam.py, но и папку (пакет) spam.

    Обратите внимание, что Python сначала производит поиск среди встроенных модулей — тех, которые встроены непосредственно в интерпретатор. Список встроенных модулей зависит от дистрибутива Python, а найти этот список можно в sys.builtin_module_names (Python 2 и Python 3). Обычно в дистрибутивах есть модули sys (всегда включён в дистрибутив), math, itertools, time и прочие.

    В отличие от встроенных модулей, которые при поиске проверяются первыми, остальные (не встроенные) модули стандартной библиотеки проверяются после директории запущенного скрипта. Это приводит к сбивающему с толку поведению: возможно «заменить» некоторые, но не все модули стандартной библиотеки. Допустим, модуль math является встроенным модулем, а random — нет. Таким образом, import math в start.py импортирует модуль из стандартной библиотеки, а не наш файл math.py из той же директории. В то же время, import random в start.py импортирует наш файл random.py.

    Кроме того, импорты в Python регистрозависимы: import Spam и import spam — разные вещи.

    Функцию pkgutil.iter_modules() (Python 2 и Python 3) можно использовать, чтобы получить список всех модулей, которые можно импортировать из заданного пути:

    import pkgutil
    search_path = ['.'] # Используйте None, чтобы увидеть все модули, импортируемые из sys.path
    all_modules = [x[1] for x in pkgutil.iter_modules(path=search_path)]
    print(all_modules)

    Чуть подробнее о sys.path

    Чтобы увидеть содержимое sys.path, запустите этот код:

    import sys
    print(sys.path)

    Документация Python описывает sys.path так:

    Список строк, указывающих пути для поиска модулей. Инициализируется из переменной окружения PYTHONPATH и директории по умолчанию, которая зависит от дистрибутива Python.

    При запуске программы после инициализации первым элементом этого списка, path[0], будет директория, содержащая скрипт, который был использован для вызова интерпретатора Python. Если директория скрипта недоступна (например, если интерпретатор был вызван в интерактивном режиме или скрипт считывается из стандартного ввода), то path[0] является пустой строкой. Из-за этого Python сначала ищет модули в текущей директории. Обратите внимание, что директория скрипта вставляется перед путями, взятыми из PYTHONPATH.

    Источник: Python 2 и Python 3

    Документация к интерфейсу командной строки Python добавляет информацию о запуске скриптов из командной строки. В частности, при запуске python <script>.py.

    Если имя скрипта ссылается непосредственно на Python-файл, то директория, содержащая этот файл, добавляется в начало sys.path, а файл выполняется как модуль main.

    Источник: Python 2 и Python 3

    Итак, повторим порядок, согласно которому Python ищет импортируемые модули:

    1. Модули стандартной библиотеки (например, math, os).
    2. Модули или пакеты, указанные в sys.path:
        1. Если интерпретатор Python запущен в интерактивном режиме:
          • sys.path[0] — пустая строка ''. Это значит, что Python будет искать в текущей рабочей директории, из которой вы запустили интерпретатор. В Unix-системах эту директорию можно узнать с помощью команды pwd.

          Если мы запускаем скрипт командой python <script>.py:

          • sys.path[0] — это путь к <script>.py.
        2. Директории, указанные в переменной среды PYTHONPATH.
        3. Директория по умолчанию, которая зависит от дистрибутива Python.

    Обратите внимание, что при запуске скрипта для sys.path важна не директория, в которой вы находитесь, а путь к самому скрипту. Например, если в командной строке мы находимся в test/folder и запускаем команду python ./packA/subA/subA1.py, то sys.path будет включать в себя test/packA/subA/, но не test/.

    Кроме того, sys.path общий для всех импортируемых модулей. Допустим, мы вызвали python start.py. Пусть start.py импортирует packA.a1, а a1.py выводит на экран sys.path. В таком случае sys.path будет включать test/ (путь к start.py), но не test/packA (путь к a1.py). Это значит, что a1.py может вызвать import other, так как other.py находится в test/.

    Всё о __init__.py

    У файла __init__.py есть две функции:

    1. Превратить папку со скриптами в импортируемый пакет модулей (до Python 3.3).
    2. Выполнить код инициализации пакета.

    Превращение папки со скриптами в импортируемый пакет модулей

    Чтобы импортировать модуль (или пакет) из директории, которая находится не в директории нашего скрипта (или не в директории, из которой мы запускаем интерактивный интерпретатор), этот модуль должен быть в пакете.

    Как было сказано ранее, любая директория, содержащая файл __init__.py, является пакетом. Например, при работе с Python 2.7 start.py может импортировать пакет packA, но не packB, так как в директории test/packB/ нет файла __init__.py.

    Это не относится к Python 3.3 и выше благодаря появлению неявных пакетов пространств имён. Проще говоря, в Python 3.3+ все папки считаются пакетами, поэтому пустые файлы __init__.py больше не нужны.

    Допустим, packB — пакет пространства имён, так как в нём нет __init__.py. Если запустить интерактивную оболочку Python 3.6 в директории test/, то мы увидим следующее:

    >>> import packB
    >>> packB
    <module 'packB' (namespace)>

    Выполнение кода инициализации пакета

    В момент, когда пакет или один из его модулей импортируется в первый раз, Python выполняет __init__.py в корне пакета, если такой файл существует. Все объекты и функции, определённые в __init__.py, считаются частью пространства имён пакета.

    Рассмотрим следующий пример:

    test/packA/a1.py

    def a1_func():
        print("Выполняем a1_func()")

    test/packA/__init__.py

    ## Этот импорт делает функцию a1_func() доступной напрямую из packA.a1_func
    from packA.a1 import a1_func
    
    def packA_func():
        print("Выполняем packA_func()")

    test/start.py

    import packA  # «import packA.a1» сработает точно так же
    
    packA.packA_func()
    packA.a1_func()
    packA.a1.a1_func()

    Вывод после запуска python start.py:

    Выполняем packA_func()
    Выполняем a1_func()
    Выполняем a1_func()

    Примечание Если a1.py вызовет import a2, и мы запустим python a1.py, то test/packA/__init__.py не будет вызван, несмотря на то, что a2 вроде бы является частью пакета packA. Это связано с тем, что когда Python выполняет скрипт (в данном случае a1.py), содержащая его папка не считается пакетом.

    Использование объектов из импортированного модуля или пакета

    Есть 4 разных вида импортов:

    1. import <пакет>
    2. import <модуль>
    3. from <пакет> import <модуль или подпакет или объект>
    4. from <модуль> import <объект>

    Пусть X — имя того, что идёт после import:

    • Если X — имя модуля или пакета, то для того, чтобы использовать объекты, определённые в X, придётся писать X.объект.
    • Если X — имя переменной, то её можно использовать напрямую.
    • Если X — имя функции, то её можно вызвать с помощью X().

    Опционально после любого выражения import X можно добавить as Y. Это переименует X в Y в пределах скрипта. Учтите, что имя X с этого момента становится недействительным. Частым примером такой конструкции является import numpy as np.

    Аргументом для import может быть как одно имя, так и их список. Каждое из имён можно переименовать с помощью as. Например, следующее выражение будет действительно в start.py: import packA as pA, packA.a1, packA.subA.sa1 as sa1.

    Пример: нужно в start.py импортировать функцию helloWorld() из sa1.py.

    • Решение 1: from packA.subA.sa1 import helloWorld. Мы можем вызвать функцию напрямую по имени: x = helloWorld().
    • Решение 2: from packA.subA import sa1 или то же самое import packA.subA.sa1 as sa1. Для использования функции нам нужно добавить перед её именем имя модуля: x = sa1.helloWorld(). Иногда такой подход предпочтительнее первого, так как становится ясно, из какого модуля взялась та или иная функция.
    • Решение 3: import packA.subA.sa1. Для использования функции перед её именем нужно добавить полный путь: x = packA.subA.sa1.helloWorld().

    Прим. перев. После переименования с помощью as новое имя нельзя использовать в качестве имени пакета или модуля для последующих импортов. Иными словами, команда вроде следующей недействительна: import packA as pA, pA.a1.

    Используем dir() для исследования содержимого импортированного модуля

    После импортирования модуля можно использовать функцию dir() для получения списка доступных в модуле имён. Допустим, мы импортируем sa1. Если в sa1.py есть функция helloWorld(), то dir(sa1) будет включать helloWorld:

    >>> from packA.subA import sa1
    >>> dir(sa1)
    ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'helloWorld']

    Импортирование пакетов

    Импортирование пакета по сути равноценно импортированию его __init__.py. Вот как Python на самом деле видит пакет:

    >>> import packA
    >>> packA
    <module 'packA' from 'packA/__init__.py'>

    После импорта становятся доступны только те объекты, что определены в __init__.py пакета. Поскольку в packB нет такого файла, от import packB (в Python 3.3.+) будет мало толку, так как никакие объекты из этого пакета не становятся доступны. Последующий вызов модуля packB.b1 приведёт к ошибке, так как он ещё не был импортирован.

    Абсолютный и относительный импорт

    При абсолютном импорте используется полный путь (от начала корневой папки проекта) к желаемому модулю.

    При относительном импорте используется относительный путь (начиная с пути текущего модуля) к желаемому модулю. Есть два типа относительных импортов:

    1. При явном импорте используется формат from .<модуль/пакет> import X, где символы точки . показывают, на сколько директорий «вверх» нужно подняться. Одна точка . показывает текущую директорию, две точки .. — на одну директорию выше и т. д.
    2. Неявный относительный импорт пишется так, как если бы текущая директория была частью sys.path. Такой тип импортов поддерживается только в Python 2.

    В документации Python об относительных импортах в Python 3 написано следующее:

    Единственный приемлемый синтаксис для относительных импортов — from .[модуль] import [имя]. Все импорты, которые начинаются не с точки ., считаются абсолютными.

    Источник: What’s New in Python 3.0

    В качестве примера допустим, что мы запускаем start.py, который импортирует a1, который импортирует other, a2 и sa1. Тогда импорты в a1.py будут выглядеть следующим образом:

    Абсолютные импорты:

    import other
    import packA.a2
    import packA.subA.sa1

    Явные относительные импорты:

    import other
    from . import a2
    from .subA import sa1

    Неявные относительные импорты (не поддерживаются в Python 3):

    import other
    import a2
    import subA.sa1

    Учтите, что в относительных импортах с помощью точек . можно дойти только до директории, содержащей запущенный из командной строки скрипт (не включительно). Таким образом, from .. import other не сработает в a1.py. В результате мы получим ошибку ValueError: attempted relative import beyond top-level package.

    Как правило, абсолютные импорты предпочтительнее относительных. Они позволяют избежать путаницы между явными и неявными импортами. Кроме того, любой скрипт с явными относительными импортами нельзя запустить напрямую:

    Имейте в виду, что относительные импорты основаны на имени текущего модуля. Так как имя главного модуля всегда "__main__", модули, которые должны использоваться как главный модуль приложения, должны всегда использовать абсолютные импорты.

    Источник: Python 2 и Python 3

    Примеры

    Пример 1: sys.path известен заранее

    Если вы собираетесь вызывать только python start.py или python other.py, то прописать импорты всем модулям не составит труда. В данном случае sys.path всегда будет включать папку test/. Таким образом, все импорты можно писать относительно этой папки.

    Пример: файлу в проекте test нужно импортировать функцию helloWorld() из sa1.py.

    Решение: from packA.subA.sa1 import helloWorld (или любой другой эквивалентный синтаксис импорта).

    Пример 2: sys.path мог измениться

    Зачастую нам требуется как запускать скрипт напрямую из командной строки, так и импортировать его как модуль в другом скрипте. Как вы увидите далее, здесь могут возникнуть проблемы, особенно в Python 3.

    Пример: пусть start.py нужно импортировать a2, которому нужно импортировать sa2. Предположим, что start.py всегда запускается напрямую, а не импортируется. Также мы хотим иметь возможность запускать a2 напрямую.

    Звучит просто, не так ли? Нам всего лишь нужно выполнить два импорта: один в start.py и другой в a2.py.

    Проблема: это один из тех случаев, когда sys.path меняется. Когда мы выполняем start.py, sys.path содержит test/, а при выполнении a2.py sys.path содержит test/packA/.

    С импортом в start.py нет никаких проблем. Так как этот модуль всегда запускается напрямую, мы знаем, что при его выполнении в sys.path всегда будет test/. Тогда импортировать a2 можно просто с помощью import packA.a2.

    С импортом в a2.py немного сложнее. Когда мы запускаем start.py напрямую, sys.path содержит test/, поэтому в a2.py импорт будет выглядеть как from packA.subA import sa2. Однако если запустить a2.py напрямую, то в sys.path уже будет test/packA/. Теперь импорт вызовет ошибку, так как packA не является папкой внутри test/packA/.

    Вместо этого мы могли бы попробовать from subA import sa2. Это решает проблему при запуске a2.py напрямую, однако теперь создаёт проблему при запуске start.py. В Python 3 это приведёт к ошибке, потому что subA не находится в sys.path (в Python 2 это не вызовет проблемы из-за поддержки неявных относительных импортов).

    Обобщим информацию:

    Запускаем from packA.subA import sa2 from subA import sa2
    start.py Нет проблем В Py2 нет проблем, в Py3 ошибка (subA не в test/)
    a2.py Ошибка (packA не в test/packA/) Нет проблем

    Использование относительного импорта from .subA import sa2 будет иметь тот же эффект, что и from packA.subA import sa2.

    Вряд ли для этой проблемы есть чистое решение, поэтому вот несколько обходных путей:

    1. Использовать абсолютные импорты относительно директории test/ (т. е. средняя колонка в таблице выше). Это гарантирует, что запуск start.py напрямую всегда сработает. Чтобы запустить a2.py напрямую, запустите его как импортируемый модуль, а не как скрипт:

    1. В консоли смените директорию на  test/.
    2. Запустите python -m packA.a2.

    2. Использовать абсолютные импорты относительно директории test/ (средняя колонка в таблице). Это гарантирует, что запуск start.py напрямую всегда сработает. Чтобы запустить a2.py напрямую, можно изменить sys.path в a2.py, чтобы включить test/packA/ перед импортом sa2.

    import os, sys
    sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
    
    # Теперь это сработает даже если a2.py будет запущен напрямую
    from packA.subA import sa2

    Примечание Обычно этот метод работает, однако в некоторых случаях переменная __file__ может быть неправильной. В таком случае нужно использовать встроенный пакет inspect. Подробнее в этом ответе на StackOverflow.

    3. Использовать только Python 2 и неявные относительные импорты (последняя колонка в таблице).

    4. Использовать абсолютные импорты относительно директории test/ и добавить её в переменную среды PYTHONPATH. Это решение не переносимо, поэтому лучше не использовать его. О том, как добавить директорию в PYTHONPATH, читайте в этом ответе.

    Пример 3: sys.path мог измениться (вариант 2)

    А вот ещё одна проблема посложнее. Допустим, модуль a2.py никогда не надо запускать напрямую, но он импортируется start.py и a1.py, которые запускаются напрямую.

    В этом случае первое решение из примера выше не сработает. Тем не менее, всё ещё можно использовать остальные решения.

    Пример 4: импорт из родительской директории

    Если мы не изменяем PYTHONPATH и стараемся не изменять sys.path программно, то сталкиваемся со следующим основным ограничением импортов в Python: при запуске скрипта напрямую невозможно импортировать что-либо из его родительской директории.

    Например, если бы нам пришлось запустить python sa1.py, то этот модуль не смог бы ничего импортировать из a1.py без вмешательства в PYTHONPATH или sys.path.

    На первый взгляд может показаться, что относительные импорты (например from .. import a1) помогут решить эту проблему. Однако запускаемый скрипт (в данном случае sa1.py) считается «модулем верхнего уровня». Попытка импортировать что-либо из директории над этим скриптом приведёт к ошибке ValueError: attempted relative import beyond top-level package.

    Для решения этой проблемы лучше её не создавать и избегать написания скриптов, которые импортируют из родительской директории. Если этого нельзя избежать, то предпочтительным обходным путём является изменение sys.path.

    Python 2 vs Python 3

    Мы разобрали основные отличия импортов в Python 2 и Python 3. Они ещё раз изложены здесь наряду с менее важными отличиями:

    1. Python 2 поддерживает неявные относительные импорты, Python 3 — нет.
    2. В Python 2, чтобы папка считалась пакетом и её можно было импортировать, она должна содержать файл __init__.py. С версии Python 3.3 благодаря введению неявных пакетов пространств имён все папки считаются пакетами вне зависимости от наличия __init__.py.
    3. В Python 2 можно написать from <модуль> import * внутри функции, а в Python 3 — только на уровне модуля.

    Ещё немного полезной информации по импортам

    • Можно использовать переменную __all__ в __init__.py, чтобы указать, что будет импортировано выражением from <модуль> import *. Смотрите документацию для Python 2 и Python 3.
    • Можно использовать if __name__ == '__main__' для проверки, был ли скрипт импортирован или запущен напрямую. Документация для Python 2 и Python 3.
    • Можно установить проект в качестве пакета (в режиме разработчика) с помощью pip install -e <проект>, чтобы добавить корень проекта в sys.path. Подробнее в этом ответе на StackOverflow.
    • from <модуль> import * не импортирует имена из модуля, которые начинаются с нижнего подчеркивания _. Подробнее читайте в документации Python 2 и Python 3.

    Перевод статьи «The Definitive Guide to Python import Statements»

    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии

    А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Ошибка при импорте данных unique constraint failed
  • Ошибка при импорте базы данных sql