Home > Blockchain >  I want to import a Python3 function from a different folder with GLOBAL scope
I want to import a Python3 function from a different folder with GLOBAL scope

Time:09-01

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()

Demo: https://replit.com/@blhsing/AbsoluteJointSandbox

  • Related