I can't import all of functions from own module in other directory
my project structure:
/
|-code
|-db_orm
|-__init__.py
|-db_interface.py
|-streamlit
|-pages
|-subpage1.py
|-subpage2.py
|-main.py
i want to add functions from db_interface.py module into subpage1.py & subpage2.py file with this code:
from db_orm.db_interface import *
but i can't do it !
i am using VS Code and python 3.9.13
thanks for any help.
A manual option to import modules from other directories is SourceFileLoader.
Not following the from syntax, but a quick solution for e.g. brief trials:
from importlib.machinery import SourceFileLoader
db_interface = SourceFileLoader("db_interface",">YourSystemPath</db_interface.py").load_module()
# call
db_interface.foo() # foo being a function in db_interface
Note: >YourSystemPath< can be absolute or relative.
If you want to keep the calls only on the functions you could add further functions in between:
def foo():
db_interface.foo()
foo()
Again that will get messy for larger projects but is a quick workaround.
Related
I recently started working on an existing project.
This project is composed of several git repositories that may use each other in some hierarchy.
All repositories should be cloned to the same root directory.
Here's an example of the structure:
root_dir:
repo_a:
module1:
- a.py
- b.py
repo_b:
module1:
- c.py
- d.py
repo_c:
module1:
- e.py
- f.py
Note that I've written "module1" three times on purpose, as it really is the same name.
Now for an example of a file, let's say a.py:
from module1.b import foo
from module1.d import goo
from module1.f import zoo
def func():
foo()
goo()
zoo()
When trying to run it from the root_dir I'm having trouble, I guess due to the ambiguities and not having relative paths.
Is there a way I can run this project properly without internally changing the code?
Based on the boundary having to stick with the given structure two ways using importlib:
Concise option:
from importlib.machinery import SourceFileLoader
repo_a_module1 = SourceFileLoader("module1",">YourSystemPath</repo_a/module1.py").load_module()
repo_b_module1 = SourceFileLoader("module1",">YourSystemPath</repo_b/module1.py").load_module()
repo_c_module1 = SourceFileLoader("module1",">YourSystemPath</repo_c/module1.py").load_module()
repo_a_module1.foo()
repo_b_module1.goo()
repo_c_module1.zoo()
Another option, but with more code:
import importlib.util
repo_a = importlib.util.spec_from_file_location(
"module1", ">YourSystemPath</repo_a/module1.py")
repo_a_module1 = importlib.util.module_from_spec(repo_a)
repo_a.loader.exec_module(repo_a_module1)
repo_b = importlib.util.spec_from_file_location(
"module1", ">YourSystemPath</repo_b/module1.py")
repo_b_module1 = importlib.util.module_from_spec(repo_b)
repo_b.loader.exec_module(repo_b_module1)
repo_c = importlib.util.spec_from_file_location(
"module1", ">YourSystemPath</repo_c/module1.py")
repo_c_module1 = importlib.util.module_from_spec(repo_c)
repo_c.loader.exec_module(repo_c_module1)
repo_a_module1.foo()
repo_b_module1.goo()
repo_c_module1.zoo()
Note: >YourSystemPath< can be absolute or relative in both options.
Both examples above have a change in the calls of the imported functions (e.g. foo() -> repo_a_module1.foo() ) which is specific and may help when working with the code later on.
If you have to keep the calls you could add further functions in between:
def foo():
repo_a_module1.foo()
foo()
Based on some answers I try to be more specific.
I want to import the print and the models AND code in my main.py
I know the question gets asked a lot, but still I could not figure out whats wrong with my code!
I have a project directory like this
-project
--__init__py
--main.py
--print.py
--requests
--__init__.py
--models.py
--code.py
i want to import from print.py and * from requests
Therefore I tried to add these lines in main.py
from . import print
#or
import print
#for requests I tried
import os.path
import sys
sys.path.append('./requests')
from requests import *
all of those lines cause the same ImportError attempted relative import with no known parent ,
using Python 39
anyone an idea where the problem is?
I am very confused that this seems not to work, was it possible in older versions?
You should definitely not be doing anything with sys.path. If you are using a correct Python package structure, the import system should handle everything like this.
From the directory structure you described, project would be the name of your package. So when using your package in some external code you would do
import package
or to use a submodule/subpackage
import project.print
import project.requests
and so on.
For modules inside the package you can use relative imports. When you write
i want to import from print.py and * from requests Therefore I tried
it's not clear from where you want to import them, because this is important for relative imports.
For example, in project/main.py to import the print module you could use:
from . import print
But if it's from project/requests/code.py you would use
from .. import print
As an aside, "print" is probably not a good name for a module, since if you import the print module it will shadow the print() built-in function.
Your main file should be outside the 'project'-directory to use that as a package.
Then, from your main file, you can import using from project.print import ....
Within the project-package, relative imports are possible.
I am trying to import files (python files) from another directory but it is not working as I have tried.
/pythonproject
.main.py
.__init__.py
->folder1
->.file1.py
->.file2.py
->.__init__.py
->folder2
->.functions.py
->.globals.py
->.__init__.py
I am trying to import functions.py inside of my file2.py.
I have tried
from functions import *
import functions
#file2.py
sys.path.insert(0, '/pythonproject')
import functions
I think your friend for this case is sys.path.append.
As discovered the problem is that you are importing the file, but when you went to use a function in the file you couldn't
One solution is:
import functions
functions.NameOfFunctionHere()
There are several posts around this error I have already read, but I still don't get what I am doing wrong.
I put it into a minimal example:
Imagine I have a Doc.py, and the package Tools which includes Tool1.py and Tool2.py.
Doc.py:
from Tools import *
import sys
def __main__():
TOOL_REPORT("Tool1","Test")
def TOOL_REPORT(tool, path):
if(tool == 'Tool1'):
Tool1.REPORT(path)
elif(tool == 'Tool2'):
Tool2.REPORT(path)
else:
sys.stderr.write("This tool is not yet included in Doc. Please check TOOLS for more information.")
if __name__=="__main__": __main__()
Tool1.py:
def REPORT(path):
print("Tool1 "+path)
Tool2.py:
def REPORT(path):
print("Tool2 "+path)
If I run this, I always end up with this error:
File "Doc.py", line 15, in TOOL_REPORT
Tool1.REPORT(path)
NameError: global name 'Tool1' is not defined
I'd appreciate any hint to what is going wrong!
Your Tool1 and Tool2 submodules are not visible until explicitly imported somewhere.
You can import them in the Tools/__init__.py package file:
import Tool1, Tool2
at which point they become available for import from Tools.
Another option is to import the modules from your own code:
import Tools.Tool1, Tools.Tool2
from Tools import *
Only when explicitly imported are submodules also set as attributes of the package.
Python will treat any folder as a module when there is __init__.py file present in it. Otherwise it will just be another folder for python and not a module from which it can import things. So just add init.py file in your Tool folder (so it will become module in pythonic terms) and then you can import that module in other python scripts.
One more things for better practice instead of using
from Tools import *
Always provide the file name of library specifically which you want to import like in your case you should use it like this
from Tools import Tool1, Tool2
This will enhance the code readbility for others and for you too.
I want to import foo-bar.py, this works:
foobar = __import__("foo-bar")
This does not:
from "foo-bar" import *
My question: Is there any way that I can use the above format i.e., from "foo-bar" import * to import a module that has a - in it?
Starting from Python 3.1, you can use importlib :
import importlib
foobar = importlib.import_module("foo-bar")
( https://docs.python.org/3/library/importlib.html )
In Python 2, you can't. foo-bar is not an identifier. rename the file to foo_bar.py
It's possible since Python 3.1+, see Julien's answer.
If import is not your goal (as in: you don't care what happens with sys.modules, you don't need it to import itself), just getting all of the file's globals into your own scope, you can use execfile
# contents of foo-bar.py
baz = 'quux'
>>> execfile('foo-bar.py')
>>> baz
'quux'
>>>
Solution: If you can't rename the module to match Python naming conventions, create a new module to act as an intermediary:
New module foo_proxy.py:
tmp = __import__('foo-bar')
globals().update(vars(tmp))
Module doing the import main.py:
from foo_proxy import *
If you can't rename the original file, you could also use a symlink:
ln -s foo-bar.py foo_bar.py
Then you can just do:
from foo_bar import *
Like other said you can't use a - in python naming, there are many workarounds, one such workaround which would be useful if you had to add multiple modules from a path is using sys.path
For example if your structure is like this:
foo-bar
├── barfoo.py
└── __init__.py
import sys
sys.path.append('foo-bar')
import barfoo
This was my scenario: I have a python library cloned in a git submodule which has a dash in its name:
|- python-my-lib
| `- mylib.py
`- my-script.py
It took me a long time to figure out the equivalent of:
# Do NOT use this!
sys.path.insert(1, './my-lib')
from mylib import MyClass
Appending the path is not an option, as it would only work if you run the script within the same directory. If you do /home/user/bin/my-script.py, this will fail.
This is the solution:
import importlib
mylib_module = importlib.import_module("python-my-lib.mylib")
MyClass = mylib_module.MyClass
Feel free to further improve this solution, if you know a simpler solution.
Python has issues with dash -. So use importlib instead.
You can run your test scripts just like this -
# importlib, because python has issues with dash '-' in module names
import importlib
img2txt = importlib.import_module("img2txt-textextractor")
event_with_txt = {...}
event_with_no_txt = {...}
def test_no_text():
response = img2txt.handler(event=event_with_txt, context='')
assert response["body"] == '"Detect Me If You Can. "'
def test_detected_text():
response = img2txt.handler(event=event_with_no_txt, context='')
assert response["body"] == '"unable to find anything"'
Name your test code as test_someName.py. To run, from the same directory on terminal type -
pytest
in Python 3.6
I had the same problem "invalid syntax" when directly
import 'jaro-winkler' as jw
said
"No module named 'jaro-winkler'" when using:
jw = __import__('jaro-winkler')
and importlib.import_module() same.
finally i use pip uninstall the jaro-winkler module...just FYI