Package Import woes in Python - python

My structure is thus:
companynamespace/
__init__.py
projectpackage/
__init__.py
somemodule.py
companynamespace/__init__.py is empty
projectpackage/__init__.py has this line:
import companynamespace.projectpackage.somemodule as module_shortname
When I open up a python console and type import companynamespace.projectpackage (PYTHONPATH is set correctly for this), I get AttributeError: 'module' object has no attribute 'projectpackage' on the import companynamespace.projectpackage.somemodule as module_shortname line. If I remove the as module_shortname part (and make all the requisite substitutions in the rest of the file), everything imports correctly.
Can anyone tell me why this is? My Google-Fu fails me.

There is no need for absolute import in projectpackage/__init__.py, do relative one
import somemodule as module_shortname
The way you're doing it (with absolute import), would lead to circular import, which don't work very well in Python. When you're importing module, you're also calling __init__.py of parent modules. In your case, with absolute import you're also calling projectpackage/__init__.py in projectpackage/__init__.py.

Well, according to the PEP 221 your code seems to be legitimate. It could be a bug. The following workaround, which is equivalent of that expression, works for me (Python 2.6.6):
from companynamespace.projectpackage import somemodule as module_shortname
Hope it helps.

Related

Python Pylance unresolved import from class exposed by __init__.py

Issue
I'm working on updating an Python library to use modern versions of Python (the Equation library) and am having trouble with Pylance when importing from the module. The base form of the library also had this issue, but for reference, here's my fork: Antyos/Equation.
As the library describes, you are supposed to be able to import the Expression class like so:
from Equation import Expression
e = Expression("sin(x+y^2)")
This code works, however, Pylance will give the following error:
"Expression" is unknown import symbol Pylance(reportGeneralTypeIssues)
If I import the code as follows, I don't receive the error and I can get type hints.
from Equation.core import Expression
My Understanding
I roughly understand the issue--as shown in the file structure below, it makes sense that from Equation.core import Expression would work. I also understand that __init__.py is exposing the Expression class to the top level of the module. (I still don't totally get how this part works and I can't seem to find the right page/section detailing it.)
Equation
├─ __init__.py
├─ _info.py
├─ core.py # Contains Expression()
├─ equation_base.py
├─ equation_scipy.py
├─ similar.py
└─ util.py
While I'm pretty sure I could get around this issue by writing a stub (*.pyi) file, it seems redundant (to me) to create a stub file for a class that I already have direct access to; why would I need to redefine something that's already there? However, it is also likely that I don't completely understand how stub files / module imports work and this is the right way.
I'm sure this issue has been addressed before, but I think I've been using the wrong terminology. What am I missing?
In __init__.py I believe you are performing relative import:
try:
from Equation.core import Expression
except ImportError:
from core import Expression
The correct way to perform relative import here is to put . in front of core like this .core.
For example:
try:
from Equation.core import Expression
except ImportError:
from .core import Expression
This fixes Pylance when I tried it.
Spec reference: https://docs.python.org/3/reference/import.html#package-relative-imports
I ran into a problem in which I was having the following error within vscode:
"some_module" is unknown import symbol
It turned out to be that the folder structure where the module was contained changed but the way to import it remained. The problem was that some old pycache existed in my local working copy within the old folder structure. After removing all of them, pylance started to work normally.

how do i correctly import a package in python?

Hello everyone im currently learning python and i im having some problems importing modules and packages. Actually i think is more of a problem with vscode.
i have this package called "paquete" with a module (funciones) that i want to import to my "main" with some fuctions in it to test if it all works correctly but i still getting "emphasized items and unresolved-import" warnings.
but for some reason it works just fine.
is more of a annoying thing.
EDIT:
module with the function "funcion"
the warning that appears in the main folder "prueba" is "emphasized items"
i tried what u guys told me to do but it stills shows the warnings
As you are trying to import a specific function from module in python
You should use in this manner:
from paquete import funciones
If you want to import full module then use:
import paquete
I can't tell whats in the funciones file. But normally this yellow import lines are telling you that you import functions, which you dont use.
Try this instead if you only want
funcion
to be imported.
from paquete.funcions import funcion
This is also better because you import only the functions you need, not all of the functions you declared in the other file. Also all imports of the other file will be loaded into your file if you import with an asterix.
The issue is you are doing all of this from within a directory named prueba. If you changed the import to from prueba.paquete.funciones import * it should work after you add a __init__.py file to your prueba directory. The other option is to use a relative import: from .paquete.funciones import *.
But do note that using import * is strongly discouraged when you are not working within the REPL. It's much better to import to the module and then reference things off the module, e.g. from prueba.paquete import funciones, from .paquete import funciones, or import prueba.paquete.funciones. That way you know exactly where things in your code came from without having to read the top of your file.
pip3 intall "name"
Use Pycharm, rather than Vscode

Why cannot import sub module?

My project structure like this:
/project
main.py
/a_module
__init__.py
/sub_module
__init__.py
some_file.py
main.py
from a_module import main_api
a_module/__init__.py
from sub_module import sub_api
sub_module/__init__.py
from some_file import detail_api
In a_module/__init__.py gives Unable to import 'sub_module' error.
Why I cannot import 'sub_module'?
When I change to the relative path solve the error.
from .sub_module import sub_api
But I don't understand, does __init__.py design for public the API of the module? Why don't treat sub_module as a module instead of a directory? it's such a bad design to me...
__init__.py is executed when you import the package that contains it. But it's not your problem. Your problem is that module imports are always absolute unless explicitly relative. That means that they must chain from some directory in sys.path. By default this includes the working directory, so when you run main.py from within project, it can find a_module, and nothing else.
from sub_module import sub_api
In a_module/__init__.py doesn't work though, because imports are always absolute unless explicitly relative. So that import says "starting from some sys.path root, find a top level package named sub_module and import sub_api from it". Since no such module exists you get an error. from .sub_module import sub_api works because you opted into relative imports, so it doesn't start over from sys.path.
For an example of why you would do this, I'll give you something that broke in our own code back in the Python 2 days before absolute import by default was the law (from __future__ import absolute_import enabled the Py3 behavior, which is how we fixed it, but despite what the docs say, it was never enabled by default in Py2, the only enabled by default behavior was relative imports). Our layout was:
teamnamespace/
module.py
math/
mathrelatedsubmodule.py
othermathsubmodule.py
Now, we innocently thought hey, we'll put all our packages under a single shared top level namespace, and subpackages cover broad categories within them, and since we had a lot of additional utilities for basic mathematics, we put them under teamnamespace.math. Problem was, for the non-math modules, like teamnamespace.module, when they did:
import math # or
from math import ceil
it defaulted to relative lookup, and imported teamnamespace.math as math (a thoroughly useless import, since it was a namespace package only, all the functionality was in the sub-modules), not the built-in math module. In fact, without the Python 3 behavior, there was no reasonable way to get the built-in math module from a module under teamnamespace. Whereas with the Python 3 behavior, you can get either one or both (by aliasing one or the other with as, with no ambiguity:
# Gets built-in
import math
# Gets teamnamespace.math
from . import math

"No module named..." with certain project structure

I have the following project structure:
MainScript.py
ExampleFolder
├ MainImport.py
└ SecondaryImport.py
MainScript.py: import ExampleFolder.MainImport
MainImport.py: Import SecondaryImport
When I try to run MainImport.py it gets no errors, but when I try to run MainScript.py, I get an import error that says No module named 'SecondaryImport'.
My question is simple - is there any way that I can import only MainImport.py from MainScript.py without getting this error, and importing SecondaryImport.py? Thanks in advance!
I have also tried adding a blank file named __init__.py to the ExampleFolder, but the error still appears. I also read Python's official documentation, but I could not find the problem. Am I missing something? (:
I think using the statement import ExampleFolder.SecondaryImport would work.
If it does, the error might be happening because as mentioned in docs, import statements will usually start searching your main project directory where the python interpreter was called if your module is not in python itself.
Another way would be to use relative import statement like this:
import .secondaryimport in order to tell the python interpreter to look in the current directory. Hope this helps!
Taking a look at these links will help, I think (It helped me when I was stuck in a similar problem):
https://docs.python.org/3/library/sys.html#sys.path
https://realpython.com/absolute-vs-relative-python-imports/
I have also tried adding a blank file named __init__.py to the ExampleFolder
That's the way - you're creating a Python package from a directory that way. And with packages you have got namespace directory.file where file is a Python file also known as module in Python world.
Then you can do from mainscript.py:
from examplefolder import mainimport
For importing inside package you may use the following syntax inside mainscript.py:
import secondaryimport
and use it in that mainscript.py as:
sevondaryimport.SomeClass()
or you may just do:
from secondaryimport import SomeClass
and use it like:
SomeClass()
Btw, use lowercase in all the cases except classes names - only they should have CamelCase names.

Python - import error

I've done what I shouldn't have done and written 4 modules (6 hours or so) without running any tests along the way.
I have a method inside of /mydir/__init__.py called get_hash(), and a class inside of /mydir/utils.py called SpamClass.
/mydir/utils.py imports get_hash() from /mydir/__init__.
/mydir/__init__.py imports SpamClass from /mydir/utils.py.
Both the class and the method work fine on their own but for some reason if I try to import /mydir/, I get an import error saying "Cannot import name get_hash" from /mydir/__init__.py.
The only stack trace is the line saying that __init__.py imported SpamClass. The next line is where the error occurs in in SpamClass when trying to import get_hash. Why is this?
This is a pretty easy problem to encounter. What's happening is this that the interpreter evaluates your __init__.py file line-by line. When you have the following code:
import mydir.utils
def get_hash(): return 1
The interpreter will suspend processing __init__.py at the point of import mydir.utils until it has fully executed 'mydir/utils.py' So when utils.py attempts to import get_hash(), it isn't defined because the interpreter hasn't gotten to it's definition yet.
To add to what the others have said, another good approach to avoiding circular import problems is to avoid from module import stuff.
If you just do standard import module at the top of each script, and write module.stuff in your functions, then by the time those functions run, the import will have finished and the module members will all be available.
You then also don't have to worry about situations where some modules can update/change one of their members (or have it monkey-patched by a naughty third party). If you'd imported from the module, you'd still have your old, out-of-date copy of the member.
Personally, I only use from-import for simple, dependency-free members that I'm likely to refer to a lot: in particular, symbolic constants.
In absence of more information, I would say you have a circular import that you aren't working around. The simplest, most obvious fix is to not put anything in mydir/__init__.py that you want to use from any module inside mydir. So, move your get_hash function to another module inside the mydir package, and import that module where you need it.

Categories