From Import in Python is not importing my modules - python

I have several custom module scrips in my python project that are all in a folder that is one directory down named "modules". After about a day of use on every machine I touch, importing these modules starts spitting out this error:
ImportError: cannot import name 'letters' from 'modules' (C:\Program Files\Python39\lib\site-packages\modules.py)
The code for importing custom modules is here.
from modules import letters
from modules import sfx
from modules import bgm
from modules.colors import colors, hex2dec
from modules import lessons
from modules import sessions
from key import key
The project folder looks like this (folders and files unrelated to the issue excluded):
formapp
├───modules
│ ├───bgm.py
│ ├───bot_ir.py
│ ├───chat.py
│ ├───colors.py
│ ├───formbot.py
│ ├───ir.py
│ ├───lessons.py
│ ├───letters.py
│ ├───sessions.py
│ └───sfx.py
├───app.py
├───key.py
For the most part, sys.path.append(r"modules") had worked to solve this issue however hex2dec in colors.py still caused errors. Regardless, of the 15 people working on this project this error only appears for me so I should not have to append a new folder to search for modules. The only thing that separates me from the other 15 people is that I was using formbot.py
Here is the code for formbot.py.
import requests
import time
class FormBot():
def __init__(self, username, password, timeout=0, host='127.0.0.1', port=420) :
self.host = '192.168.10.69'
self.port = 420
self.username = username
self.password = password
self.loggedin = False
time.sleep(timeout)
self.login()
print('logged in as', username)
#change "userType": "login", to "usertype": "new" on first time use
def login(self):
loginAttempt = requests.post(url="http://"+self.host+":"+str(self.port)+"/login", data={"username": self.username, "password": self.password, "userType": "new", "bot": "True", "forward":"/"})
#forbius login
Forbius = FormBot('Forbius', 'Password#1')
I have also tried reinstalling Python entirely and that has not worked.
To test, I tried running a fresh copy of the main branch on a computer affected by this issue and got the same error. The same code works fine on other machines.

try adding an __init__.py file inside the modules folder
inside the __init__.py file put:
from .letters import *
from .sfx import *
from .bgm import *
.
.
.

You'll need to add a file called __init__.py to your modules folder. The file can be empty. Review this SO thread for more details: What is __init__.py for?

Related

Pytest not able to run test where script A importing another script B in the same folder level as A and giving me ModuleNotFoundError

I am trying to run the unit test using pytest in this project, here main_0.py is importing s3 file.
I am getting ModuleNotFoundError: no module named 's3'
Project Folder Structure
some_project
└───src
├───main
│ └───lambda_function
│ └───some
│ main_0.py
│ s3.py
│
└───test
└───unittest
└───lambda_function
└───some
test_main_0.py
test_s3.py
main_0.py
from s3 import PrintS3
def lambda_handler():
obj = PrintS3()
res = obj.print_txt()
return res
s3.py
class PrintS3:
def __init__(self) -> None:
self.txt = "Hello"
def print_txt(self):
print(self.txt)
return self.txt
test_main_0.py
import unittest
class TestSomeMain(unittest.TestCase):
def test_main_0(self):
from src.main.lambda_function.some.main_0 import lambda_handler
res = lambda_handler()
assert res == "Hello"
test_s3.py is empty.
I also tried adding an empty __init__.py file in both the dir but still the same error
Project Folder Structure after adding __init__.py file
some_project
└───src
├───main
│ └───lambda_function
│ └───some
│ main_0.py
│ s3.py
│ __init__.py
│
└───test
└───unittest
└───lambda_function
└───some
test_main_0.py
test_s3.py
__init__.py
the command I am using to run pytest:
python -m pytest ./src/test
and I am inside some_project folder and also using main_0.py instead of main.py because to not get confused with main folder
Edit 2:
I am to run the test case successfully by adding sys.path in the test_main_0.py file but it is breaking linting and hinting in the code editor (vscode) it didn't broke the linting and hinting, both import statement works but is there any better way.
new test_main_0.py:
import unittest
import os
import sys
sys.path.append(os.path.abspath("./src/main/lambda_function/some/"))
class TestSomeMain(unittest.TestCase):
def test_main_0(self):
from src.main.lambda_function.some.main_0 import lambda_handler # this works
from main_0 import lambda_handler # this also works but break linting and hinting in the code editor
res = lambda_handler()
assert res == "Hello"
could you please try
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from some.s3 import PrintS3
def lambda_handler():
obj = PrintS3()
res = obj.print_txt()
return res
I found a somewhat working solution.
added setUp() and tearDown() methods in the class for inserting and removing path in sys.path
path in sys.path is the location of the directory where the main_0.py and s3.py is located
import unittest
import os
import sys
class TestSomeMain(unittest.TestCase):
def setUp(self) -> None:
sys.path.insert(0, os.path.abspath("./src/main/lambda_function/some/"))
def tearDown(self) -> None:
sys.path.remove(os.path.abspath("./src/main/lambda_function/some/"))
def test_main_0(self):
from src.main.lambda_function.some.main_0 import lambda_handler
res = lambda_handler()
assert res == "Hello"
also update the test command in the terminal:
python -m pytest ./src/test/unittest/lambda_function/some --cov ./src/main/lambda_function/some --cov-report html

Importing Python modules in large projects and "ModuleNotFoundError"

I have faced a rather famous issue while importing my python modules inside the project.
This code is written to replicate the existing situation:
multiply_func.py:
def multiplier(num_1, num_2):
return num_1 * num_2
power_func.py:
from math_tools import multiplier
def pow(num_1, num_2):
result = num_1
for _ in range(num_2 - 1):
result = multiplier(num_1, result)
return result
The project structure:
project/
│ main.py
│
└─── tools/
│ __init__.py
│ power_func.py
│
└─── math_tools/
│ __init__.py
│ multiply_func.py
I've added these lines to __init__ files to make the importing easier:
__init__.py (math_tools):
from .multiply_func import multiplier
__init__.py (tools):
from .power_func import pow
from .math_tools.multiply_func import multiplier
Here is my main file.
main.py:
from tools import pow
print(pow(2, 3))
Whenever I run it, there is this error:
>>> ModuleNotFoundError: No module named 'math_tools'
I tried manipulating the sys.path, but I had no luck eliminating this puzzling issue. I'd appreciate your kind help. Thank you in advance!
You messed it up in the "power_func.py" file.
You have to use . before math_tools to refer to the current directory module.
Update "power_func.py" as bellow, it works perfectly.
from .math_tools import multiplier

Loading variables from python file failed when running batch program

Ever since i'v started to load variables from separate file I encountered failure during running python programs with batch files with selenium webdriver.
lets say i have:
project/
│
│── project/
│ ├── schedule.py
│ └── database/
| └── config.py
inside scheudle.py i got this lines:
from database.config import *
driver = Chrome(options=c_options)
driver.get(url)
password_field = driver.find_element_by_id('password')
password_field.clear()
password_field.send_keys(password)
and inside config.py i got this lines:
password = keyring.get_password(...)
the error i get:
password_field.send_keys(password)
{'text': "".join(keys_to_typing(value)),
for i in range(len(val)):
TypeError: object of type 'NoneType' has no len()
But note this, after i'm opening the python file itself in PyCharm, everything works fine, the batch and all, even if i close PyCharm, its like its loading the vars or something...
I would love to know how to fix this problem,
Thanks.
Have you tried naming the imported config.py:
from database import config
...
password_field.send_keys(config.password)

Trouble instantiating class in a subdirectory

Have a module in a subdirectory and when I try to import it, I get a NameError: namefoois not defined. When I put the class code directly into the __main__.py file it works fine. __init__.py files are empty.
I've tried the following all with other errors:
MyProject/
├── __init__.py
├── __main__.py
├── foo/
│ ├── bar.py
│ ├── __init__.py
bar.py
class Bar:
def __init__(self):
print( 'am here' )
pass
__main__.py
from MyProject import foo
#from MyProject import bar # errors with cannot import bar from MyProject
#from foo import bar # errors with No module named foo
if __name__ == '__main__':
w = Bar()
Is there perhaps a better way to organise this?
The Bar class is in the file bar.py, so I think you'd need to do
from MyProject.foo import bar
w = bar.Bar()
or
from MyProject.foo.bar import Bar
w = Bar()
You didn't share your foo/__init__.py, but you could fix the situation by adding something like this to it:
from .bar import Bar
That adds Bar to the namespace of foo and causes Python to find Bar when you just import foo.
However, you would probably do well to look at a few standard examples for writing a package. For one, you probably shouldn't name your project MyProject, as that name signals it's a class (with TitleCase). Naming it 'project' further confuses the issue, as it appears you're writing a package, so my_package sounds about right.
If you dont know from what direcrory file will be runed then use . to show where package is
from .foo.bar import Bar
or
from .foo import bar
w = bar.Bar()
or
import .foo
w = foo.bar.Bar()
. before package name means that package lockated in same directory with current file

Importlib.import_module will not import the module even though the param is the abs path

I have my .py module which is in C:\Python_Projects\MyModules\ with the name button_generator.py.
My code goes something like this:
module_path='C:\\Python_Projects\\MyModules'
module_name='button_generator.py'
sys.path.append(module_path)
try:
limp=importlib.import_module(module_name.split('.')[0])
except:
print 'module import error'
I have tried other versions aswell:
importlib.import_module(module_name) without the split
importlib.import_module('C:\Python_Projects\MyModules\button_generator.py')
importlib.import_module('C:\Python_Projects\MyModules\button_generator')
The folder C:\Python_Projects\MyModules is in my sys.path as I checked during debug.
Why wouldn't the module import?
I suggest you to reorder your project directories and avoid calling other modules which are not in your current directory project. You'll avoid those kind of errors.
For example, let's organize our project directories and folders to look something like this:
MyProjectFolder/
├── main.py
└── modules
├── __init__.py
└── MyLib.py
NB: Don't forget to add an empty file called __init__.py
MyLib.py :
#!/usr/bin/python3
class MyLib:
def __init__(self):
self.say_hello = "Hello i'm in modules/MyLib"
def print_say_hello(self):
print(self.say_hello)
main.py:
#!/usr/bin/python3
# from folder.file import class
from modules.MyLib import MyLib
class MainClass:
def __init__(self):
my_lib = MyLib() # load MyLib class
my_lib.print_say_hello() # access to MyLib methods
### Test
if __name__ == '__main__':
app = MainClass()
In terminal when i run:
$ python3 main.py
output:
Hello i'm in modules/MyLib
So here we have successfully imported the class in modules/MyLib.py into our main.py file.
I found the error:
After treating the ImportError exception by printing it's args, I noticed that button_generator.py had an Import that was not resolving. Basically, button_generator.py could not be imported because it had a wrong import.

Categories

Resources