0

I have a Django project that I've been working on for a while. I came to the point where I wanted to load a significant amount of data into my Postgres database. I set aside a new Django project with sqlite3 just to work out the code and run some tests to make sure everything was inserted properly.

Everything seemed fine until I got to the point where I actually wanted to test the insert script.

ImportError: attempted relative import with no known parent package

The error refers to this line in the script:

from .models import Statute

As of right now, this has no red squiggly line on it. models.py and this script are right beside each other in the same directory:

$ tree

└── parsecodetree
    ├── db.sqlite3
    ├── manage.py
    ├── parsecodetree
    │   ├── asgi.py
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── ustitles
        ├── admin.py
        ├── apps.py
        ├── __init__.py
        ├── insert504.py
        ├── insert_script_results
        ├── migrations
        ├── models.py
        ├── t10p1b.html
        ├── tests.py
        └── views.py

I found this trick in an old David Beazely video:

parsecodetree/ustitles/__init__.py:
from .models import *
print("This is ustitles.__init__")
“This is ustitles.__init__” does not print.

Commenting or uncommenting ‘from .models import *’ seems to make no difference.

However:

/home/malikarumi/Projects/uscode/parsecodetree/parsecodetree/__init__.py:
print("This is parsecodetree.__init__")
"This is parsecodetree.__init__" does print.

But apparently it also gets an error:

This is parsecodetree.__init__
Traceback (most recent call last):
<...snip…>
ModuleNotFoundError: No module named 'parsecodetree.parsecodetree'

I found this from RealPython.com more confusing than helpful. If __init__.py is not required, why do I even have this issue to begin with?

https://realpython.com/lessons/package-initialization/

Note: Much of the Python documentation states that an __init__.py file must be present in the package directory when creating a package. This was once true. It used to be that the very presence of __init__.py signified to Python that a package was being defined. The file could contain initialization code or even be empty, but it had to be present.

Starting with Python 3.3, Implicit Namespace Packages were introduced. These allow for the creation of a package without any __init__.py file. Of course, it can still be present if package initialization is needed. But it is no longer required.

I saw a lot of stuff about setting the __package__ variable. But where do I put this assignment? I tried settings. That didn’t work.

I don’t understand the mapping from python “package” to django “Project” BASE_DIR == “Project”, but are both also == “package” or “__package__”?

In my setup, are both parsecodetree and ustitles “packages”? Whether I set them as == __package__ or not? Whether they have __init__.py or not?

This SO post makes it seem like every directory needs an __init__.py, just the opposite of the RealPython lesson. It doesn't seem DRY, either.

This gets red squiggly lines:

from ustitles.models import Statute

and a traceback to boot:

This is ustitles.__init__
Traceback (most recent call last):
<...snip…>
ModuleNotFoundError: No module named 'parsecodetree.parsecodetree'

But do you notice? Now “This is ustitles.__init__” prints!

Along the same lines, how do you run “-m” with PyCharm “run”? Turns out this is still an open question: https://intellij-support.jetbrains.com/hc/en-us/community/posts/360003879119-how-to-run-python-m-command-in-pycharm-?page=1#community_comment_5925736517010

Malik A. Rumi
  • 1,855
  • 4
  • 25
  • 36
  • Can you tell us which command line you are using and from which directory? – Laurent LAPORTE Jun 06 '22 at 03:49
  • "Everything seemed fine until I got to the point where I actually wanted to test the insert script." How exactly did you attempt to do this? Which file is "the insert script"? Where the code says `from .models import *`, what are you hoping this will accomplish? What is in `models.py`, and how does that relate to the problem? Do we need to see all these file names in order to understand the problem? Please read [mre]. – Karl Knechtel Jun 06 '22 at 04:00
  • @LaurentLAPORTE: I am using PyCharm, so I hit the 'run' button and it runs the script in the Django console. >>> os.getcwd() '/home/malikarumi/Projects/uscode/parsecodetree/ustitles' – Malik A. Rumi Jun 06 '22 at 15:03
  • @KarlKnechtel: The insert script is called "insert504.py". I am running this from within PyCharm. I was hoping the "import *" would give me access to the model I am trying to use. models.py has my Django models in it. The script is to insert data into the database table created from this model. – Malik A. Rumi Jun 06 '22 at 15:06
  • "I am running this from within PyCharm." What is the current working directory when you do so? What command does PyCharm issue? – Karl Knechtel Jun 06 '22 at 15:49
  • @KarlKnechtel: >>> os.getcwd() '/home/malikarumi/Projects/uscode/parsecodetree/ustitles'. Not sure what you mean by 'what command PyCharm issues", but I see this in the output, so maybe this is what you are referring to? runfile('insert504.py', wdir='/home/malikarumi/Projects/uscode/parsecodetree/ustitles', is_module=True) – Malik A. Rumi Jun 06 '22 at 20:05
  • Yep, that's the problem. Relative imports are not designed to work while you are "inside" the package, because this way the package root is not on the list of paths that Python searches for modules and packages (`sys.path`). (Absolute imports typically won't work either, since they'll have been specified starting at the package root.) See e.g. https://stackoverflow.com/questions/14132789 – Karl Knechtel Jun 06 '22 at 20:49

0 Answers0