Importing across a python package - python

pkg/
__init__.py
foo.py
bar.py
baz.py
I have a bunch of module imports that are the same across foo.py, bar.py, and baz.py.
Is there a way I can do the imports in __init__.py? What would I have to write in foo.py?

Placing the imports in __init__.py would be a bad idea; __init__.py is used as the contents of your module object, so it is a public interface. Also, __init_.py is imported initially when your package is imported, while you don't actually need the imports to occur until your submodules need them.
The best approach is to put common code in an internal detail module, marked with a single initial underscore (meaning "private"), e.g. _imports.py, then in your other files write from ._imports import *.

You guessed the right way of doing this, but I can make this a little more formal and give (hopefully) a clearer explanation than the one you found elsewhere. If you want to modularize imports, which depending on your coding philosophy could be a good or bad idea in and of itself (transparency vs. code reuse), whether or not the imports happen in __init__.py you can import your imports from another script. For instance:
"""import_scripts.py"""
import numpy as np
import scipy as sp
...
"""actual_code.py"""
from import_scripts import *
# np and sp are now in scope
Importing from __init__.py is mostly the same, you just traditionally use a relative import instead if you're accessing it from the same module:
# To import form __init__
from . import *
Important to note though, that these kind of imports will only work if you run these python scripts explicitly as modules rather than as scripts. This means:
python -m foo
instead of
python foo.py
Important, but subtle distinction.
Hope that helps. Let me know if you have any more questions.

Related

How to import module inside package

Folder structure:
foo/
bar.py
__init__.py
test.py
foo/__init__.py has import bar
I am running test.py which has import foo
How do I get __init__.py to import bar.py?
ModuleNotFoundError: No module named 'foo'
Why does Python not create a new scope for my package and make the root for imports the foo directory?
Relative paths seem to not work either (I'm receiving a SyntaxError), although I'm looking for a solution that allows absolute paths.
import .bar
Two unacceptable answers:
I can't use import foo.bar. I need the foo package to have its own independent layer/scope so I can move it around anywhere in my computer and import it from anywhere. This means the root could change and import foo.bar will not always work.
I can't add the foo folder to my path. Obviously this would clutter the path and name conflicts could easily happen. Commence sense would say that this package's files should be separated from the path of what's using it.
Maybe there's a solution to add this package's directory to the path only for the scope of that package, somewhere in __init__.py?
Per PEP 328, the import X syntax is purely for absolute imports; since bar is not a top-level module here, the only valid import X syntax is import foo.bar.
The correct way to import bar from foo's __init__.py is:
from . import bar
Your point about wanting "absolute paths", but also wanting something like import .bar is impossible; even if import .bar worked, that's clearly a relative path (in that it only makes sense relative to the module that executes it; .bar would not make sense if imported outside of the foo package).
As for "Why does Python not create a new scope for my package and make the root for imports the foo directory?" the simple example is to imagine your sub-module is named math, not bar. What does:
import math
mean in this context? If it means your sub-module, how do you get the built-in, top-level math module? These problems (which I've encountered in Python 2 code when I failed to include from __future__ import absolute_import) are why PEP 328 and default absolute imports exist; one syntax is always absolute (removing ambiguity), and you can use the relative import syntax to perform relative imports (also without ambiguity) when needed.
Okay so you are having an error in __init__.py file in import bar right?
Well this shouldn't blow up but an easy alternate to this is from . import bar
EDIT
I understood the error occurs due to hierarchy and that __init__.py has a top level hierarchy. I found the following article of great help. Also see ShadowRanger's answer to this question.

How to import from the __init__.py in the same directory?

Suppose I have a module rules with the following structure:
rules
├── conditions.py
├── __init__.py
In the script conditions.py, I'd like to import a class called RuleParserError defined in __init__.py. However, I haven't been able to figure out how to do this. (Following Python: How to import from an __init__.py file? I've tried
from . import RuleParserError
but this leads to an ImportError: cannot import name RuleParserError when trying to run conditions.py as __main__).
I see 'import from parent module' as an anti-pattern in Python. Imports should be the other way around. Importing from modules's __init__.py is especially problematic. As you noticed, importing module foo.bar from foo/bar.py involves importing foo/__init__.py first, and you may end up with a circular dependency. Adding a print("Importing", __name__) to your init files helps see the sequence and understand the problem.
I'd suggest that you moved the code you want to import in conditions.py from __init__.py to a separate lower-level module, and just import some names from that module in __init__.py to expose it at higher level.
Let's suppose that you had some class Bar in your __init__.py. I'd reorganize it the following way.
__init__.py:
from bar import Bar # exposed at the higher level, as it used to be.
bar.py:
class Bar(object): ...
conditions.py:
from . import Bar # Now it works.
Ideally an __init__.py should contain nothing but imports from lower-level modules, or nothing at all.
If you get
ImportError: attempted relative import with no known parent package
when you do like
import . from something
especially from the script executed, just try
from __init__ import something
Even though it could be problematic when there are many __init__.pys in sys.path, it would be helpful in some simple situaions.
adding __package__ on top the script
__package__ = "pkg.dir.dir"
resolving the issue
in this case
__package__ = "rules"

More relative import oddness: .. notation

I noticed I've made about 5 questions asking about relative imports, each with working solutions but with different situations. The more I read the docs and the more I try out different cases the more I'm getting confused and questioning whether I'm actually reading the words correctly.
From pep 328:
A single leading dot indicates a relative import,
starting with the current package. Two or more leading dots
give a relative import to the parent(s) of the current package,
one level per dot after the first.
My understanding is that "current package" is the keyword here. What IS the "current package"? Is it the package of the module where execution begins? (ie: the file with __ name __ == "__ main __").
Anyways, here is a simple situation of me using .. notation.
main/
lib/
__init__.py
myLib.py
plugin/
__init__.py
needLib.py
run.py
run.py imports needLib: from plugin import needLib
needLib imports myLib: from ..lib import myLib
What's going through my head: (needLib) goes up a package, go into lib, grab myLib
Here is how I execute: python run.py
Result: Attempted relative import beyond toplevel package
But when I changed the import call to from .lib import myLib, it works.
I don't understand why the latter works and the .. notation doesn't. Of course, main isn't a package, so how about I just throw in a init.py there as well, resulting in
main/
lib/
__init__.py
myLib.py
other/
__init__.py
needLib.py
__init__.py
run.py
But that didn't make a difference; still attempting to import beyond top-level package
Check out this question: python: forcing relative imports to search from script file
The .. notation actually worked! Now that I think about it, I don't understand why it works. Execution in that scenario started 2 levels up from where the relative import takes place, while execution in this scenario starts 1 level up from where the relative import takes place. Other than where I begin execution, the situation is identical.
Both are me saying "go up one directory, go into the lib package, and grab the module you want".
What is the key difference between this situation and the referenced situation? Why does .. work there, but not here? Does me using 2.6 have anything to do with this? Or perhaps how I am executing it? python run.py
As you found out, from ..lib import myLib does not work as main is not a package. Relative imports only work within a module's own package. In your example, lib and other are two distinct packages.
Putting an __init__.py in main only works if you move run outside of the newly created main package, so that the current directory (part of sys.path) is not within a package.

Import a module, from inside another module

Basically I have written two modules for my Python Program. I need one module to import the other module.
Here is a sample of my file structure.
test_app
main.py
module_1
__init__.py
main.py
module_2
__init__.py
main.py
Main.py is able to import either of the two modules, but I need module_1 to import module_2, is that possible?
If you started your program from test_app/main.py, you can just use from module_1 import main in test_app/module_2/main.py file.
If you add an (empty) __init__.py to test_app, test_app will be a package. This means that python will search for modules/packages a bit smarter.
Having done that, in module1, you can now write import test_app.module2 (or import .. module2) and it works.
(This answer was combined from other comments and answers here, hence CW)
Yes. If your PYTHONPATH environment variable is set to test_app, you should be able to import module1 from module2 and vice versa.
I assume that you run your program like this:
python test_app/main.py
and that the program imports module1.main, which in turn imports module2.main. In that case there is no need to alter the value of PYTHONPATH, since Python has already added the test_app directory to it. See the Module Search Path section in the Python docs.
This question ask been answered by the official python documents, in the section called Intra-package References. python modules
The submodules often need to refer to each other.
You don't need to care about the PYTHONPATH, declaration of the relative path will do.
For your case,
just type "import .. module2" in the module_1/main.py
sure does.
In your module_1 module. In any file:
from module_2 import your_function, your_class

Acessing other py file's class

I have two files:
a.py
b.py
How can I access my ABC123 class defined in a.py from b.py?
import a
x = a.ABC123()
or
from a import ABC123
x = ABC123()
will do the job, as long as a.py and b.py are in the same directory, or if a.py is in a directory in sys.path or in a directory in your environment's $PYTHONPATH. If neither of those is the case, you might want to read up on relative imports in PEP328.
In spite of being several years old, Importing Python Modules might be worth reading for a more thorough overview of importing from other modules. It does seem beginner-friendly, too.
You need to import the objects from the other file:
from a import ABC123
For a good discussion on this topic please see Importing Python Modules:
The import and from-import statements
are a constant cause of serious
confusion for newcomers to Python.
Luckily, once you’ve figured out what
they really do, you’ll never have
problems with them again.
This note tries to sort out some of
the more common issues related to
import and from-import and everything.

Categories

Resources