I am working in Python3.x on Linux Mint 21 and here is my directory structure:
└── main_dir/
├── all_files_dir/
│ ├── a_files_dir/
│ │ └── file_a.py
│ ├── b_files_dir/
│ │ └── file_b.py
│ └── c_files_dir/
│ └── file_c.py
└── runner.py
Here is the content of file_a.py
def function_a():
print("a ran")
return "a return value "
Here is the content of file_b.py
def function_b():
print("b ran")
return "b return value "
Here is the content of file_c.py
def function_c():
print("this function STARTS running!!!")
result_of_function_a = a()
result_of_function_b = b()
results_of_both_functions = result_of_function_a result_of_function_b
print("results_of_both_functions", results_of_both_functions)
Here is the content of runner.py
from all_files_dir.a_files_dir.file_a import function_a as a
a() # This Works!
from all_files_dir.b_files_dir.file_b import function_b as b
b() # This Works!
from all_files_dir.c_files_dir.file_c import function_c as c
c() # This STARTS working and prints 'this function STARTS running!!!'
# This FAILS eventually!!!
Here is the error message:
a ran
b ran
this function STARTS running!!!
Traceback (most recent call last):
File ".../main_dir/runner.py", line 8, in <module>
c() # This STARTS working and prints 'this function STARTS running!!!'
File ".../main_dir/all_files_dir/c_files_dir/file_c.py", line 3, in function_c
result_of_function_a = a()
NameError: name 'a' is not defined
I understand that I can add imports to function_c(): But I want to import all functions with a GLOBAL scope instead so that I do not have to modify anything in all_files_dir and I want to modify ONLY runner.py
How do I import function_a() as 'a()' and function_b() as 'b()' and function_c as 'c()' into runner.py in such a way that they can all see each other in GLOBAL scope and use each other easily without having to modify function_c() by adding more import statements to function_c()??? I only want to modify runner.py but cant figure out how....
I tried
global from all_files_dir.c_files_dir.file_c import function_c as c
but that does not work either...
I also suspect that importing functions with a "global scope" is probably not the best practice, but that is what I want anyways because the code is for a small home project, not for a corporate production work compliance environment.
CodePudding user response:
In Python there's no such thing as a truly "global" variable. A "global" variable in Python is just a name bound to the namespace of the module that defines it. Since every module has its own namespace, having the names a
and b
imported to the main module does not mean that the file_c
module would magically inherit them when imported by the main module, which means that you also need the following lines in your file_c.py
:
from all_files_dir.a_files_dir.file_a import function_a as a
from all_files_dir.b_files_dir.file_b import function_b as b
You can also use relative import in file_c.py
if the relative paths to file_a
and file_b
will always be the same:
from ..a_files_dir.file_a import function_a as a
from ..b_files_dir.file_b import function_b as b
EDIT: If you would don't want the module file_c
to have its own namespace but would rather run file_c.py
as if it were included inline in the main program, you can simply read file_c.py
as a file and execute its content with exec
in runner.py
:
with open('main_dir/all_files_dir/c_files_dir/file_c.py') as file:
exec(file.read())
c = function_c
c()
To prevent unnecessary pollution of the main program's namespace, however, you can pass to exec
a dict as the locals
argument to selectively access names that are defined by the execution of file_c
:
with open('main_dir/all_files_dir/c_files_dir/file_c.py') as file:
names = {}
exec(file.read(), globals(), names)
c = names['function_c']
c()