No module named - python

I have a python project with this structure: (This is not a real project, only for testing)
ImportTest
ImportPersonsTest\
ImportPerson\
ImportPerson.py
RunImportPersonTest.py
RunImportTests.py
I want this tests to call each other. E.g :
RunImportTests.py calls a method in RunImportPersonTest.py, and RunImportPersonTest.py calls a method ImportPerson.py
RunImportPersonTest:
import os
import sys
sys.path.insert(0, os.getcwd() + "../../../")
from ImportPerson import ImportPerson
RunImportTests
import os
import sys
sys.path.insert(0, os.getcwd() + "../../")
from ImportPersonsTest import RunImportsPersonTest
I have success when I run ImportPerson.py and RunImportPersonTest.py, but when I try to run RunImportTests I get this error :
Traceback (most recent call last):
File "xxx\LiClipse Workspace\SystemTest\ImportTest\RunImportTests.py", line 4, in <module>
from ImportPersonsTest import RunImportsPersonTest
File "xxx\LiClipse Workspace\SystemTest\ImportTest\ImportPersonsTest\RunImportsPersonTest.py", line 4, in <module>
from ImportPerson import ImportPerson
ImportError: No module named 'ImportPerson'
Any suggestions?
Edit
New Structure
ImportTest
ImportPersonsTest\
ImportPerson\
ImportPerson.py
__init__.py
RunImportPersonTest.py
__init__.py
RunImportTests.py
__init__.py

Looks like you don't have any __init__.py files in your project. Python needs those files to be able to import modules from folders. The good news is, they are very easy to make: most of the time, they don't need anything in them, they just have to exist.
See: https://docs.python.org/2/tutorial/modules.html#packages

I think your use of os.getcwd() is flawed.
My guess is that you're running your program from the ImportTest directory and so your current working directory will already allow you to do the first import without any need to fix up your path. When you then try the second import, adding ".../ImportTest/../../.." or ".../ImportTest/../.." isn't helping Python find it.
To fix it either add the ImportPersonsTest directory to your path or use a suitably modified name in the import (ensuring you have your init files as already flagged) - e.g.
from ImportPersonsTest.ImportPerson import ImportPerson

There is two basic problem:
os.getcwd() as other os functions return path with no separator at the end. In fact you insert xxx\LiClipse Workspace\SystemTest\ImportTest../../../ which is not a valid path
As mention by #peter, using os.getcwd() is bad idea - it's depend on your location when you run the script. Use:
sys.path.append(os.path.dirname(__file__)) (insert recommend only at special cases)
But,
It seems that none of this caused your problem. It's only insert bad stuff to your sys.path. Your importing need to work good cause all the importing done from the self-module-dir, where python firstly search for the requested module.
I copy your package to mine machine - and both runs well!
I fix one spelling bug (RunImportsPersonTest -- RunImportPersonTest) - maybe there is other spelling problem

Related

Correct syntax for import statement

Newbie here
I want to import a class from a file in another directory, in this case:
C:\Users\jose_\Desktop\my_ref\stack_class.py, using the from - import statement. I have an init.py file in said directory but cannot find the right sintax anywhere.
How do you put C:\Users\jose_\Desktop\my_ref\stack_class.py in the import part?
I have tried using these other two ways:
exec(open("file path on windows").read())
and the import sys and sys.path.insert
they both work, trying to do it with the import statement.
from C:\Users\jose_\Desktop\my_ref\stack_class.py import Stack #Error here
foo = Stack()
print(type(foo))
Error
File "C:/Users/jose_/OneDrive/Mis_Documentos/Educacion/Linkedin/Ex_Files_Python_Data_Structures_Queues/Exercise_Files/Ch02/02_02/End/main2.py", line 4
from C:\Users\jose_\Desktop\my_ref\stack_class.py import Stack
^
SyntaxError: invalid syntax
As far as I know, you cannot import from a file path in Python.
You can only import by passing a module name:
import module.submodule
# then
module.submodule.sth()
or
from module.submodule import sth
# then
sth()
And Python will search module/submodule.py and module/submodule/__init_.py in all the directories in sys.path.
So if you want to import from a file in another directory created by yourself (not included in the sys.path list) you have to append that directory to the list to tell Python where to find that module. Try to run:
import sys
sys.path.append('C:\\Users\\jose_\\Desktop\\my_ref')
from stack_class import Stack
# then
foo = Stack()
print(type(foo))
Edit
If you don't want to append to sys.path, you need to move your module to one of the diretories in sys.path, for example, the current directory . is also in sys.path, or Python won't know where the module is (C:\ is not in sys.path).
Python never imports from directories that are not included in sys.path (via import statements, I mean)!
Did you make sure to switch your forward slashes "\" with back slashes "/" ?
try using:
sys.path.extend('file path here')
to add the folder path to your python path, that way python knows where to look for the stack_class module - either that or navigate to the folder before importing
also make sure in the folder your init file is called __init__.py
you should then be able to do
from stack_class import Stack

Python3 unable to find a package module

I have a file called dns_poison.py that needs to call a package called netscanner. When i try and load the icmpscan module from dns_poison.py I get this message:
ModuleNotFoundError: No module named 'icmpscan'
I've done a sys.path and can confirm that the correct path is in place. The files are located at D:\PythonProjects\Networking\tools and D:\PythonProjects appears when I do a sys.path.
Here is my directory structure:
dns_poison.py
netscanner/
__init__.py
icmpscan.py
Code snippets for the files are as follows:
dns_poison.py
import netscanner
netscanner\__init__.py
from icmpscan import ICMPScan
netscanner\icmpscan.py
class ICMPScan:
def __init__(self, target, count=2, timeout=1):
self.target = target
self.count = count
self.timeout = timeout
self.active_hosts = []
# further code below here....
I don't understand why it cannot find the module, as I've used this exact same method on other python projects without any problems. Any help would be much appreciated.
When you run python dns_poison.py, the importer checks the module path then the local directory and eventually finds your netscanner package that has the following available:
netscanner
netscanner.icmpscan
netscanner.icmpscan.ICMPScan
Now I ask you, where is just icmpscan? The importer cannot find because well, it doesnt exist. The PYTHONPATH exists at wherever dns_poison.py resides, and doesn't append itself to include the absolute path of any imported modules because that simply not how it works. So netscanner can be found because its at the same level as dns_poison.py, but the importer has no clue where icmpscan.py exists because you havent told it. So you have two options to alter your __init__.py:
from .icmpscan import ICMPScan which works with Python 3.x
from netscanner.icmpscan import ICMPScan which works with both Python 2.x/3.x
Couple of references for you:
Python Import System
Python Modules recommend you ref section 6.4.2 Intra-package References
The most simple way to think about this is imports should be handled relative to the program entry-point file. Personally I find this the most simple and fool-proof way of handling import paths.
In your example, I would have:
from netscanner.icmpscan import ICMPScan
In the main file, rather than add it to init.py.

Getting "ImportError: attempted relative import with no known parent package" when running from Python Interpreter

I'm creating a modular app using Flask blueprints feature. As a result, my directory structure is like this:
project
__init__.py
config.py
mould.py
modules
__init__.py
core
__init__.py
core.py
db.py
models.py
The modules directory here is not be confused with Python modules, they are for giving a modular structure to my project (core module, foo module, bar module, etc.). Now each folder in the modules directory (and a module inside it with same name such as core.core) is dynamically imported in my main flask app (mould.py) by doing this:
for item in os.listdir("modules"):
if not os.path.isfile("modules" + os.sep + item) and not item.startswith("__"):
ppath = "modules" + "." + item
fullpath = "modules" + "." + item + "." + item
module = importlib.import_module(fullpath)
app.register_blueprint(module.app)
print("Registered: " + ppath)
As a result of this, I'm unable to do this in the module scripts like db.py:
import models
Since it gives a path error as the entire module is being executed at the project level, so I had to do this:
from . import models
This solves the issue and I'm able to successfully import all modules. However, when I go to the core modules directory for some troubleshooting and start the python interpreter, it doesn't allow me to import the db module:
>>> import db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "db.py", line 7, in <module>
from . import models
ImportError: attempted relative import with no known parent package
Is there a way around this? So, that I can import the db module successfully in the code as well as interpreter?
I know I'm late to the party, but I think I've found a solution to this problem. Hopefully this will be useful to someone else working on a large Python project.
The trick is to try one import format and fall back to the other format if the first fails.
Approach 1
db.py
try:
# Assume we're a sub-module in a package.
from . import models
except ImportError:
# Apparently no higher-level package has been imported, fall back to a local import.
import models
On the plus side, this approach is pretty simple, but doesn't scale well (module names are duplicated). Scaling can be improved by importing programmatically.
Approach 2 (not recommended)
db.py
import importlib
root = 'project.modules.core'
my_modules = ['core', 'models']
for m in my_modules
try:
globals()[m] = importlib.import_module(root + '.' + m)
except ImportError:
globals()[m] = importlib.import_module(m)
globals() is the global symbol table.
Of course, now this functionality needs to be duplicated in every module. I'm not sure that's actually an improvement over the first approach. However, you can separate this logic out into its own independent package that lives somewhere on pythonpath.
Approach 3
package_importer.py
import importlib
def import_module(global_vars, root, modules):
for m in modules
try:
global_vars[m] = importlib.import_module(root + '.' + m)
except ImportError:
global_vars[m] = importlib.import_module(m)
db.py
import package_importer
root = 'project.modules.core'
my_modules = ['core', 'models']
package_importer.import_module(globals(), root, my_modules)
This may be a bit outdated, but maybe someone else will benefit of my answer. Since python2 und python3 have different default import behavior, you have to determine between these two python versions.
Python 2.X
The default behavior for import models is to look up first the relative and then the absolute search path order. Therefore it should work.
However, in Python 3.X the default behavior for import models is to look for the model only in the absolute paths (called absolute imports). The current package core gets skipped and since the module db cannot be found anywhere else in the sys.path search path, it throws an error. To resolve this issue you have to use the import statement with dots from . import models to make clear that you are trying to import from a relative directory.
If you are interested to learn more about importing python modules, I suggest you to start your research with the following key words: module search path, python package import and relative package imports

Custom Python module structure

I am currently doing a personal coding project and I am trying to build a module, but I don't know why my structure doesn't work the way it's supposed to:
\mainModule
__init__.py
main.py
\subModule_1
__init__.py
someCode_1.py
someCode_2.py
\subModule_2
__init__.py
otherCode.py
I want to be able to run the following code from main.py:
>>> from subModule_1 import someCode_1
>>> someCode_1.function()
"Hey, this works!"
>>> var = someCode_2.someClass("blahblahblah")
>>> var.classMethod1()
>>> "blah blah blah"
>>> from subModule2 import otherCode
>>> otherCode("runCode","#ff281ba0")
However, when I try to import someCode_1, for example, it returns an AttributeError, and I'm not really sure why. Is it to do with the __init__.py file?
REVISIONS
Minimal, Complete and verifiable (I hope...)
\mainDir
__init__.py # blank file
main.py
\subDir
__init__.py # blank file
codeFile.py
Using this...
#main.py file
import subDir
subDir.codeFile.function()
And this...
#codeFile.py file
def function():
return "something"
...it returns the same problem mentioned above**.
** The exact error is:
Traceback (most recent call last):
File "C:\...\mainDir\main.py", line 2, in <module>
subDir.codeFile.function()
AttributeError: module 'subDir' has no attribute 'codeFile'
Credits to #jonrsharpe: Thanks for showing me how to use Stack Overflow correctly.
You have two options to make this work.
Either this:
from subdir import codeFile
codeFile.function()
Or:
import subdir.codeFile
subdir.codeFile.function()
When you import subDir, it does three things:
executes the code in mainDir/subDir/__init__.py (i.e. in this case does nothing, because this file is empty)
imports the resulting module under the name subDir locally, which will in turn make it an attribute of the mainDir module;
registers the new import globally in the sys.modules dictionary (because the import is being performed from a parent module mainDir, the name is completed to 'mainDir.subDir' for the purposes of this registration);
What it does not do, because it hasn't been told to, is import subDir.codeFile. Therefore, the code in codeFile.py has not been run and the name codeFile has not yet been imported into the namespace of mainDir.subDir. Hence the AttributeError when trying to access it. If you were to add the following line to mainDir/subDir/__init__.py then it would work:
import codeFile
Specifically, this will:
run the code in codeFile.py
add the resulting module as an attribute of the mainDir.subDir module
store a reference to it as yet another entry in sys.modules, this time under the name mainDir.subDir.codeFile.
You could also achieve the same effect from higher up the module hierarchy, by saying import subDir, subDir.codeFile instead of just import subDir in your mainDir.main source file.
NB: When you test this from the command line or IDE, make sure that your current working directory (queried by os.getcwd(), changed using os.chdir(wherever) ) is neither mainDir nor subDir. Work from somewhere else—e.g. the parent directory of mainDir. Working from inside a module will lead to unexpected results.

How to import a module from the root dir having another with same name in a descendent package?

I'm using python 2.7.10.
I understand that there is many questions related to this. I'm starting this question because none of answers I found in StackOverflow answers my doubts. My goal here is to clarify my understanding about the Python import machinery with the help of the community.
I have a project with a structure like this:
./
./config.py
./modules
./modules/__init__.py
./modules/config.py
config.py
VALUE = 1
modules/config.py
import config
print(config.VALUE)
In this module, I want to get the VALUE constant from the module in the root dir and print it. When I run the config in modules package I get the following error:
$ python modules/config.py
Traceback (most recent call last):
File "modules/config.py", line 1, in <module>
import config
File "/test/modules/config.py", line 2, in <module>
print(config.VALUE)
AttributeError: 'module' object has no attribute 'VALUE'
I understand that the import config statement imports the module in the current directory instead the one in the root dir. So I need to add a kind of hack to allow it import the module in the root dir:
modules/config.py
def import_from_root(name):
import os
import imp
root_path = os.path.dirname(os.path.abspath(__name__))
root_module = os.path.join(root_path, '{}.py'.format(name))
return imp.load_source('root_'.format(name), root_module)
print(import_from_root('config').VALUE)
Now it works:
$ python modules/config.py
1
But I'm wondering if this is the best way to do this. So, I have the following questions:
Is there a more pythonic way to solve this?
To move to Python 3.x will improve this?
Please, consider that I don't want to change the directory structure or the names of the modules.
This works if you'd rather change your current working directory than your sys path:
from os import chdir
chdir('/')
import config
this might be better if you have other resources in root. Both this and the above solution are more parsimonious and pythonic than your current solution.

Categories