Import in a module fails because __name__ is __main__ - python

Here is my project structure:
Project
main.py
myPackage/
subfolder1/
__init__.py
script11.py
script12.py
subfolder2/
__init__.py
script2.py
__init__.py
in main.pyI import script2.py the following way :
from myPackage.subfolder2 import script2 as script2
then, I call a function from script2.py in main.py with :
bar = script2.foo()
and in script2 I need to import a function from script1 :
from ..subfolder1.script11 import my_function
and it breaks with the error :
attempted relative import with no known parent package
I have inspected the __name__ variable and indeed it has the value __main__. How can I manage that properly ?

All you should have to do is change your import in main.py to from myPackage.subfolder2 import script2. I set up a directory and some files in this way, using that import, and the script runs as expected:
main.py
myPackage/
subfolder1/
script11.py
subfolder2/
script2.py
script11.py
def bar():
return 10
script2.py
from ..subfolder1.script11 import bar
def foo():
x = bar()
print('foo is', x)
main.py
from myPackage.subfolder2 import script2 as s2
s2.foo()
Running:
>>> py .\main.py
foo is 10
Some notes:
I'm assuming Python 3, since Python 2 was deprecated beginning of this year
In Python 3, the __init__.py files aren't necessary to make a package, but having them doesn't hurt anything. You can leave them out if you want.
The as script2 part in from subfolder2 import script2 as script2 is redundant. It will already be imported as script2.

Related

Importing a file that imports another file

I would like to import a file that also imports another file.
I currently have the following directory structure:
.
├── main.py
└── foo
├── file1.py
├── file2.py
└── file3.py
With the following code:
# main.py
from foo.file1 import func1
func1()
# foo/file1.py
from file2 import func2
from file3 import func3
def func1():
# Do stuff
func2()
func3()
if __name__ == "__main__":
# Do some other stuff
func1()
# foo/file2.py
from file3 import func3
def func2():
# Do stuff
func3()
# foo/file3.py
def func3():
# Do stuff
If I run main.py, I get ModuleNotFoundError: No module named 'file2'.
I could replace the line from file2 import func2 in foo/file1.py with from foo.file2 import func2 and do the same for the file3 import but then I could not run foo/file1.py on its own.
What would be the recommended way to fix this?
Python3 doesn't support Implicit Relative Imports e.g. from file2 import func2, we need to use Explicit Relative Imports e.g. from .file2 import func2.
In foo/file1.py change:
from file2 import func2
from file3 import func3
To:
from .file2 import func2
from .file3 import func3
And in foo/file2.py change:
from file3 import func3
To:
from .file3 import func3
You might want to read: Absolute vs Relative Imports in Python

Import error raised when importing file1.py in file2.py where file2.py also imports file1.py [duplicate]

This question already has answers here:
Circular dependency in Python
(5 answers)
Closed 3 years ago.
I my Python Pyramid files, File2.py is importing File1.py and File1.py is importing File2.py, which is creating an infinite loop and raising Import error. I need to import these to use the public varibles of the classes as well as therir functions. How do i achieve this ?
I tried below :
File2.py
Class File2 :
def __init__(self, sessionId):
from server.eventmanager.file1 import File1 # : Doesnt Work
if __name__ == "__main__":
from server.eventmanager.file2 import File2 # : Doesnt Work(Tried both(init+ main)/either
def myFunc(self):
print(File1.myvar)
File1.py
from /server/modules/mymodule/file2 import File2
Class File1:
def __init__(self):
pass
myvar = False
def updateMyVar(self,updatedvar):
cls.myvar=updatedvar
#Do Something
File "/server/eventmanager/file1.py", line 7, in <module>
from server.modules.mymodule.File2 import file2
File "/server/modules/mymodule/file2.py", line 13, in <module>
from server.eventmanager.File1 import file1
ImportError: cannot import name 'file1'
I think you are looking for cyclic dependency in python
Circular dependency in Pythonenter link description here
you can have look how to resolve them.
You can add above your first import an if clause.
If I understood you right then you start your code with File2.py.
In this case you should do it like that:
if __name__ == "__main__":
import file1
If you run File2.py __name__ will be __main__. As a result the if - clause is true and you import File1.py. Well now File1.py imports File2.py but this time __name__ isn't __main__ because it doesn't run as a "main-file". This time __name__ will be File1 and File1 doesn't import Test2 anymore because the if clause stops it, but it still has the code of it because it already imported it one time.
Edit:
Ok I got it! You have to put the if __name__ == "__main__" clause at the top of your code in your File1.py:
if __name__ == "__main__":
from server.eventmanager.file2 import file2 # Doesnt Work(Tried both(init+ main)/either
from server.eventmanager.file1 import File1 # : Doesnt Work
class File2:
def __init__(self, sessionId):
pass
def myFunc(self):
print(File1.myvar)

Override function in a module with complex file tree

I have a module module containing 2 functions a and b splited into 2 different files m1.py and m2.py.
The module's file tree:
module/
__init__.py
m1.py
m2.py
__init__.py contains:
from .m1 import a
from .m2 import b
m1.py contains:
def a():
print('a')
m2.py contains:
from . import a
def b():
a()
Now, I want to override the function a in a main.py file, such that the function b uses the new function a. I tried the following:
import module
module.a = lambda: print('c')
module.b()
But it doesn't work, module.b() still print a.
I found a solution, that consists in not importing with from . import a but with import module.
m2.py becomes:
import module
def b():
module.a()

Execute sh in subdirectory from main.py script?

I am trying to do the following thing.
I have a python project with this dir-tree:
Project dir
|
|___main.py
|___module
|
|__a.py
|__a.sh
a.py has a class with a method that runs the script:
class A():
def run():
os.system('a.sh')
And a.sh creates a file:
touch a.txt
And main.py instantiates an object of class A and calls run():
a = A()
a.run()
When main is called, I get an error saying that the script a.sh is not found. I get why that happens, it's because the working dir is equal to the project root path, but how can I make it work so that the file created ends up in the root path?
I want to call main.py and end up with this configuration.
Project dir
|
|___a.txt
|___main.py
|___module
|
|__a.py
|__a.sh
I could replace the call to a.sh in a.py to
os.system('module/a.sh')
And it would work, but it does not look clean to me.
Code in the a.py module can extract the name of the directory it is in and use that in the os.system() call. This is what I mean:
File a.py:
import os
class A():
def run(self):
my_directory = os.path.dirname(__file__)
script_path = os.path.join(my_directory, 'a.sh')
os.system(script_path)
a = A()
a.run()

Python - Intra-package importing when package modules are sometimes used as standalone?

Sorry if this has already been answered using terminology I don't know to search for.
I have one project:
project1/
class1.py
class2.py
Where class2 imports some things from class1, but each has its own if __name__ == '__main__' that uses their respective classes I run frequently. But then, I have a second project which creates a subclass of each of the classes from project1. So I would like project1 to be a package, so that I can import it into project2 nicely:
project2/
project1/
__init__.py
class1.py
class2.py
subclass1.py
subclass2.py
However, I'm having trouble with the importing with this. If I make project1 a package then inside class2.py I would want to import class1.py code using from project1.class1 import class1. This makes project2 code run correctly. But now when I'm trying to use project1 not as a package, but just running code from directly within that directory, the project1 code fails (since it doesn't know what project1 is). If I set it up for project1 to work directly within that directory (i.e. the import in class2 is from class1 import Class1), then this import fails when trying to use project1 as a package from project2.
Is there a way to have it both ways (use project1 both as a package and not as a package)? If there is a way, is it a discouraged way and I should be restructuring my code anyway? Other suggestions on how I should be handling this? Thanks!
EDIT
Just to clarify, the problem arrises because subclass2 imports class2 which in turn imports class1. Depending on which way class2 imports class1 the import will fail from project2 or from project1 because one sees project1 as a package while the other sees it as the working directory.
EDIT 2
I'm using Python 3.5. Apparently this works in Python 2, but not in my current version of python.
EDIT 2: Added code to class2.py to attach the parent directory to the PYTHONPATH to comply with how Python3 module imports work.
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
Removed relative import of Class1.
Folder structure:
project2
- class3.py
- project1
- __init__.py
- class1.py
- class2.py
project2/project1/class1.py
class Class1(object):
def __init__(self):
super(Class1, self).__init__()
self.name = "DAVE!"
def printname(self):
print(self.name)
def run():
thingamy = Class1()
thingamy.printname()
if __name__ == "__main__":
run()
project2/project1/class2.py
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from class1 import Class1
class Class2(Class1):
def childMethod(self):
print('Calling child method')
def run():
thingamy = Class2()
thingamy.printname()
thingamy.childMethod()
if __name__ == "__main__":
run()
project2/class3.py
from project1.class2 import Class2
from project1.class1 import Class1
class Class3(Class2):
def anotherChildMethod(self):
print('Calling another child method')
def run():
thingamy = Class3()
thingamy.printname()
thingamy.anotherChildMethod()
if __name__ == "__main__":
run()
With this setup each of class1, 2 and 3 can be run as standalone scripts.
You could run class2.py from inside the project2 folder, i.e. with the current working directory set to the project2 folder:
user#host:.../project2$ python project1/class2.py
On windows that would look like this:
C:\...project2> python project1/class2.py
Alternatively you could modify the python path inside of class2.py:
import sys
sys.path.append(".../project2")
from project1.class1 import class1
Or modify the PYTHONPATH environment variable similarly.
To be able to extend your project and import for example something in subclass1.py from subclass2.py you should consider starting the import paths always with project2, for example in class2.py:
from project2.project1.class1 import class1
Ofcourse you would need to adjust the methods I just showed to match the new path.

Categories

Resources