scy,
@scy@chaos.social avatar

Imports in Python can be confusing.

I just saw someone ask "why do I have to prepend a dot to import a file in the same directory?"

That depends on whether the file with the import statement is in a package or not.

But, whether Python considers it to be in a package depends on how you imported (or ran) that file. You can't determine it from the file's content or the filesystem structure!

Check alt text (image description) for explanations of the examples.

#Python #import

Running four commands from the parent directory. "python3 mypkg/abs_import.py" prints "in pkg", because Python found mymod.py in the same directory as the file it has been asked to run. That's because sys.path (which is used to define search order for modules) is initialized like this (quoting from the docs): "The first entry in the module search path is the directory that contains the input script, if there is one. Otherwise, the first entry is the current directory, which is the case when executing the interactive shell, a -c command, or -m module." "python3 mypkg/rel_import.py" throws an ImportError: "attempted relative import with no known parent package". Just because you're running a file in a subdirectory doesn't make this directory a package. "python3 -m mypkg.rel_import" prints "in pkg", because Python is now interpreting mypkg as a package name, has found the rel_import module in that package, and is able to do relative imports from there. "python3 -m mypkg.abs_import" prints "top level". Remember the documentation from above: If there is no input script (and there isn't, we're asking Python to resolve and run a module instead), sys.path will first look in the current directory, i.e. the one containing the mypkg package, because that's the one we're currently in.
We now change into the mypkg directory with a "cd" command. "python3 abs_import.py" prints "in pkg", because Python is going to look for "mymod" in the directory containing the input script (which happens to be the current directory, but that's not relevant). "python3 rel_import.py" throws an ImportError "attempted relative import with no known parent package" again. Understandably, because Python has no way of knowing that the directory we're currently in can be interpreted as a package. "python3 -m abs_import" prints "in pkg", because sys.path first looks for mymod the current directory. "python3 -m rel_import" raises an ImportError "attempted relative import with no known parent package" again. That's because, in contrast to what we did in the last example in the previous screenshot, we're now just using "rel_import" as the module name we're asking Python to run, without the "mypkg" prefix. Adding the prefix wouldn't work, because our current directory is already inside the mypkg package and Python (correctly) wouldn't find another "mypkg" directory in it. But without the prefix, Python doesn't know that the "rel_import" module resides in a package at all.
We now move into the parent directory again ("cd ..") and delete the top-level mymod.py file. Then, we attempt the examples from the second image again. "python3 mypkg/abs_import.py" prints "in pkg" as before, because Python found mymod.py in the same directory as the file it has been asked to run. "python3 mypkg/rel_import.py" throws an ImportError: "attempted relative import with no known parent package", just like before, because it interprets the file path as a script to run, not as a module in a package. "python3 -m mypkg.rel_import" prints "in pkg", just like before, because Python is interpreting mypkg as a package name, has found the rel_import module in that package, and is able to do relative imports from there. "python3 -m mypkg.abs_import" throws a ModuleNotFoundError "no module named 'mymod'. Before, it printed "top level", but now we have deleted the top-level mymod.py file that it was importing.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • python
  • DreamBathrooms
  • cubers
  • thenastyranch
  • InstantRegret
  • Youngstown
  • rosin
  • slotface
  • Durango
  • ngwrru68w68
  • khanakhh
  • kavyap
  • everett
  • mdbf
  • magazineikmin
  • JUstTest
  • cisconetworking
  • GTA5RPClips
  • osvaldo12
  • tacticalgear
  • ethstaker
  • modclub
  • tester
  • Leos
  • normalnudes
  • provamag3
  • megavids
  • anitta
  • lostlight
  • All magazines