Python import statement is not working for parent package - python

I'm using Python 3.9.5.
Based on this post, I'm trying to reuse some functions from the parent directory. Here's my code hierarchy:
github_repository
src
base
string_utilities.py
validation
email_validator.py
I also have __init__.py in all folders. In ALL of them.
Here's the string_utilities.py content:
def isNullOrEmpty(text: str):
return text is not None and len(text) > 0
And here's the email_validator.py content:
from src.base import string_utilities
def is_email(text: str):
if string_utilities.isNullOrEmpty(text):
return False
# logic to check email
return True
Now when I run python email_validator.py, I get this error:
ModuleNotFoundError: No module named 'src'
I have changed that frustrating import statement to all of these different forms, and I still get no results:
from ...src.base import string_utilities
which results in:
ImportError: attempted relative import with no known parent package
import src.base.string_utilities
Which causes compiler to not know the isNullOrEmpty function.
import ...src.base.string_utilities
Which results in:
Relative imports cannot be used with "import .a" form; use "from . import a" instead
I'm stuck at this point on how to reuse that function in this file. Can someone please help?

Related

import of Python class from module in package

My structure looks something like this:
project/->
app.py
checker/->
exc.py
anc.py
My files are simple:
# app.py
from checker.exc import ExampleClass
# checker/exc.py:
from anc import AnotherClass
class ExampleClass(AnotherClass):
print('Example')
# checker/anc.py:
class AnotherClass:
print('AAAA')
When I run exc.py inside checker folder everything works ok, same when
I run app.py with module from package checker everything works perfect.
But when I run app.py which uses class from checker.exc, and exc need anc. I have an error ModuleNotFoundError: No module named anc
Realise this is a duct tape solution.
Change exc.py to:
try:
from anc import AnotherClass
print('abs import')
except ModuleNotFoundError:
from .anc import AnotherClass
print('rel import')
class ExampleClass(AnotherClass):
print('Example')
That way you can use absolute import when debugging, for instance, but rely on relative import when importing it running app.py on it's own.
The order in which you attempt to import them should reflect the expected use, with the one most expected to be used being attempted first. The error is the same if you switch the attempts.
Since the code is being run from the project folder, in order for exc.py to find anc.py you need to change exc.py to the following:
from .anc import AnotherClass
class ExampleClass(AnotherClass):
print('Example')
As berna1111's comment suggests, this may cause problems when running exc.py directly.

ImportError on Python

I'm new to python and I'm having this problem that I can't figure it out.
My file structure is:
enter image description here
On Criador.py I have several functions, for example:
def doSomething():
pass
def doSomethingElse():
pass
and Im trying to use one of this functions on the Controller.py file:
The first thing I did was, on the Controller.py:
import Controller.Criador
and then tried to use that function as:
Controller.Criador.doSomething()
After running Controller.py, I got this error:
ModuleNotFoundError: No module named 'Controller.Criador'; 'Controller' is not a package
I tried several other things, like:
from . import Criador
or
from Controller.Criador import doSomething
or
from Controller import Criador
and nothing helped, just changed the errors to:
ImportError: cannot import name 'Criador'
and
ModuleNotFoundError: No module named 'Controller.Criador'; 'Controller' is not a package
and
ImportError: cannot import name 'Criador'
Can someone give me a light about this? I'm using PyCharm and it does not give me any error when I declare the imports, only when I run the file
If Controller.py and Criador.py are in the same folder, you can do this inside Controller.py:
import Criador
Criador.doSomething()

Python ImportLib 'No Module Named'

I'm trying to use a variable as a module to import from in Python.
Using ImportLib I have been successfully able to find the test...
sys.path.insert(0, sys.path[0] + '\\tests')
tool_name = selected_tool.split(".")[0]
selected_module = importlib.import_module("script1")
print(selected_module)
... and by printing the select_module I can see that it succesfully finds the script:
<module 'script1' from 'C:\\Users\\.....">
However, when I try to use this variable in the code to import a module from it:
from selected_module import run
run(1337)
The program quits with the following error:
ImportError: No module named 'selected_module'
I have tried to add a init.py file to the main directory and the /test directory where the scripts are, but to no avail. I'm sure it's just something stupidly small I'm missing - does anyone know?
Import statements are not sensitive to variables! Their content are treated as literals
An example:
urllib = "foo"
from urllib import parse # loads "urllib.parse", not "foo.parse"
print(parse)
Note that from my_module import my_func will simply bind my_module.my_func to the local name my_func. If you have already imported the module via importlib.import_module, you can just do this yourself:
# ... your code here
run = selected_module.run # bind module function to local name

From *folder_name* import *variable* Python 3.4.2

File setup:
...\Project_Folder
...\Project_Folder\Project.py
...\Project_folder\Script\TestScript.py
I'm attempting to have Project.py import modules from the folder Script based on user input.
Python Version: 3.4.2
Ideally, the script would look something like
q = str(input("Input: "))
from Script import q
However, python does not recognize q as a variable when using import.
I've tried using importlib, however I cannot figure out how to import from the Script folder mentioned above.
import importlib
q = str(input("Input: "))
module = importlib.import_module(q, package=None)
I'm not certain where I would implement the file path.
Repeat of my answer originally posted at How to import a module given the full path?
as this is a Python 3.4 specific question:
This area of Python 3.4 seems to be extremely tortuous to understand, mainly because the documentation doesn't give good examples! This was my attempt using non-deprecated modules. It will import a module given the path to the .py file. I'm using it to load "plugins" at runtime.
def import_module_from_file(full_path_to_module):
"""
Import a module given the full path/filename of the .py file
Python 3.4
"""
module = None
try:
# Get module name and path from full path
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
# Get module "spec" from filename
spec = importlib.util.spec_from_file_location(module_name,full_path_to_module)
module = spec.loader.load_module()
except Exception as ec:
# Simple error printing
# Insert "sophisticated" stuff here
print(ec)
finally:
return module
# load module dynamically
path = "<enter your path here>"
module = import_module_from_file(path)
# Now use the module
# e.g. module.myFunction()
I did this by defining the entire import line as a string, formatting the string with q and then using the exec command:
imp = 'from Script import %s' %q
exec imp

Hiding implementation files in a package

I have a module called spellnum. It can be used as a command-line utility (it has the if __name__ == '__main__': block) or it can be imported like a standard Python module.
The module defines a class named Speller which looks like this:
class Speller(object):
def __init__(self, lang="en"):
module = __import__("spelling_" + lang)
# use module's contents...
As you can see, the class constructor loads other modules at runtime. Those modules (spelling_en.py, spelling_es.py, etc.) are located in the same directory as the spellnum.py itself.
Besides spellnum.py, there are other files with utility functions and classes. I'd like to hide those files since I don't want to expose them to the user and since it's a bad idea to pollute the Python's lib directory with random files. The only way to achieve this that I know of is to create a package.
I've come up with this layout for the project (inspired by this great tutorial):
spellnum/ # project root
spellnum/ # package root
__init__.py
spellnum.py
spelling_en.py
spelling_es.py
squash.py
# ... some other private files
test/
test_spellnum.py
example.py
The file __init__.py contains a single line:
from spellnum import Speller
Given this new layout, the code for dynamic module loading had to be changed:
class Speller(object):
def __init__(self, lang="en"):
spelling_mod = "spelling_" + lang
package = __import__("spellnum", fromlist=[spelling_mod])
module = getattr(package, spelling_mod)
# use module as usual
So, with this project layout a can do the following:
Successfully import spellnum inside example.py and use it like a simple module:
# an excerpt from the example.py file
import spellnum
speller = spellnum.Speller(es)
# ...
import spellnum in the tests and run those tests from the project root like this:
$ PYTHONPATH="`pwd`:$PYTHONPATH" python test/test_spellnum.py
The problem
I cannot execute spellnum.py directly with the new layout. When I try to, it shows the following error:
Traceback (most recent call last):
...
File "spellnum/spellnum.py", line 23, in __init__
module = getattr(package, spelling_mod)
AttributeError: 'module' object has no attribute 'spelling_en'
The question
What's the best way to organize all of the files required by my module to work so that users are able to use the module both from command line and from their Python code?
Thanks!
How about keeping spellnum.py?
spellnum.py
spelling/
__init__.py
en.py
es.py
Your problem is, that the package is called the same as the python-file you want to execute, thus importing
from spellnum import spellnum_en
will try to import from the file instead of the package. You could fiddle around with relative imports, but I don't know how to make them work with __import__, so I'd suggest the following:
def __init__(self, lang="en"):
mod = "spellnum_" + lang
module = None
if __name__ == '__main__':
module = __import__(mod)
else:
package = getattr(__import__("spellnum", fromlist=[mod]), mod)

Categories