Ex46 ModuleNotFoundError

I’m using conda 4.7.5 for managing environments and Python 3.7.3 and keep getting:

ModuleNotFoundError: No module named ‘NAME’

when trying to run NAME_tests.py individually in exercise 46, despite nosetests running successfully and my directory structure + filenames matching the book. I tried:

export PYTHONPATH=.

in the command line to fix this, as per exercise 47 and 48 student questions and still am having no luck. I also poked around this forum, Stack Overflow, and Nick Coghlan’s notes on Python’s import system traps and suspect that the culprit might be an issue with absolute vs. relative imports, but am still struggling to fix this. Any tips?

Hi, can you paste your code here so we can see exactly how you do the import?

@io_io, I followed the skeleton file for tests (NAME_tests.py) in exercise 46:

from nose.tools import *
import NAME

def setup():
print(“SETUP”)

def teardown():
print(“TEAR DOWN!”)

def test_basic():
print(“I RAN!”, end=’’)

When running NAME_tests.py individually from the command line, the full error message is:

Traceback (most recent call last):
File “NAME_tests.py”, line 2, in
import NAME
ModuleNotFoundError: No module named ‘NAME’

LMK if I should paste more code! It’s verbatim from the book.

Check if you have the latest nose version, google it a bit as far as I know it’s deprecated.
I’d move on to pytest and skip nose testing. Check how tests should be written in pytest.
When I did the exercise I didn’t have any problem, it just worked.

You need to make sure have a file named NAME.py in your current directory. Once you’re sure that’s there the you might have to force python to load it. What OS are you on?

@zedshaw I don’t have a file named NAME.py in my current directory, only a directory that contains an init .py file. My directory structure is:

  • skeleton/
    • NAME/
      • init .py
    • bin/
    • docs/
    • setup.py
    • tests/
      • NAME_tests.py
      • init .py

I call nosetests in the skeleton directory using OS 10.14.5. The ModuleNotFoundError occurs when I change directories to tests and try to run NAME_tests.py. I hadn’t done this step previously, but noticed the issue in exercise 48 when trying to get the import to work for lexicon_tests.py in exercise 48.

You need NAME.py too in the NAME Directory. Your test file tries to import a module called NAME but it doesn’t exist.

Think of the package having folders and files within. The init helps python know it’s a package (and you can do stuff with the init when you get more advanced).

So if your tests try to import NAME, it’s actually the module/file (NAME.py) it’s looking for.

@zedshaw + @gpkesley thanks for the advice! I added NAME.py to the NAME directory, so now the structure looks like:

  • skeleton
    • NAME/
      • _ init _.py
      • NAME.py
    • bin/
    • docs/
    • setup.py
    • tests
      • NAME_tests.py
      • _ init _.py

I cleared out the pycache files and am still having the same error though. Any thoughts? Is there something else I should be adding to the new NAME.py file?

Have you double-checked your setup.py includes the NAME module under packages too?

setup(
...
packages=[‘NAME’],
...

So the setup basically say here is the set up for this programme. It called, blah, blah, blah, by someone, and for it to work, you need the ‘NAME’ module which is part of this package.

@gpkesley I have! My setup.py looks like this as per LPTHW:

try:
from setuptools import setup
except ImportError:
from distutils.core import setup

config = {
‘description’: ‘My Project’,
‘author’: ‘My Name’,
‘url’: ‘URL to project’,
‘download_url’: ‘URL to download project’,
‘author_email’: ‘My email’,
‘version’: ‘0.1’,
‘install_requires’: [‘nose’],
‘packages’: [‘NAME’],
‘scripts’: [],
‘name’: ‘projectname’
}

setup(**config)

I’m going to bet you wrote:

_init_.py – underscore init underscore dot py

But it should be:

__init__.py – underscore underscore init underscore underscore dot py

In fact, I bet if you did that there you my have done it all over. The place you added the NAME.py file would require you to do this:

import NAME from NAME

So that’s probably not what you wanted. I also see you have this single underscore in tests as well. Check it. It could be just the formatting on here though.

@zedshaw I do have underscore underscore init underscore underscore dot py for all my init files in my local drive. The first time I quoted my directory structure in this forum, I believe that the double underscore acted like markup and automatically bolded init, removing said underscores, so I added a blank space and single underscore for clarification in my second comment.

tl;dr My filenames are formatted correctly, I just messed it up in commenting. Still stumped.

Have you tried an absolute path?
from .NAME import NAME
I googled and found this answer, but don’t know if you tried it:

Alright then at this point you’re going to have to make a video for us since there’s nothing else that could be wrong. If you have all the files, you’re inside skeleton and not above it, you have the correct underscores, you’ve set PYTHONPATH, then we can’t figure it out without screenshots of the fail or a video. A screenshot would work but you’d have to do:

  1. pwd and ls where you are
  2. the export PYTHONPATH
  3. The nosetest run and result.

Other mistake people make is they cd tests to try to run them. Once you do that python thinks this is the project root and tries to import files from there, so it expects tests/NAME.py to exist. Never cd down into lower directories to run things. You always stay in the project root.

If you don’t have a quick and easy recorder and you are using chrome :face_with_raised_eyebrow: the try https://chrome.google.com/webstore/detail/screen-recorder/hniebljpgcogalllopnjokppmgbhaden?hl=en

@zedshaw I finally figured this out thanks to your last bit of advice! I was cd’ing down into lower directories to run them, rather than staying in the project root. Everything works fine now, thanks!

1 Like

Thanks for sharing the solution.

Yep, the general rule is this:

Never ever CD down into a project directory. All of the modules expect your python interpreter to be located in the root (top) of the project, when you CD down into the lower directories it throws off where modules are. So, imagine you have this project:

mycode/
    bin/app.py
    code/stuff.py

Now imagine that bin/app.py has this inside it:

from code.stuff import TheThing

That import maps like this:

  • code -> code/
  • code.stuff -> code/stuff.py
  • TheThing -> code/stuff.py:class The Thing

So if you were to do a full path of python and map that to a full path on the disk it’d be:

code.stuff.TheThing ===> code/stuff.py:TheThing

That : after .py is a way of saying “Wherever TheThing is defined inside stuff.py” similar to if I wrote “code/stuff.py:42” to get line 42 of code/stuff.py.

Now, imagine if you do this:

cd bin/
python app.py

Your first line tries to load TheThing from the module code.stuff, which then causes python to do this:

  1. look in the current directory for a code/ or code.py file.
  2. Current directory is…bin/ OopS! code/ is one directory up, so this module can’t be found.

The solution is to do this:

$ cd bin/
$ python app.py
# !!ERRORRRRRRRRRRR
# oops I'm in the wrong directory
$ cd ..
$ python bin/app.py
# Ahhhhhh now we're home.
A free service run by Zed A. Shaw for learncodethehardway.org.