I'm making a module file, and I need to get the global variables of the file that is using it.
I've tried importing it, and then getting the global variables of of that, but that gets me this error:
Traceback (most recent call last):
File "C:\Users\isaac\OneDrive\Coding\python\logger\file.py", line 1, in <module>
import logger
File "C:\Users\isaac\OneDrive\Coding\python\logger\logger.py", line 3, in <module>
import file as bla
File "C:\Users\isaac\OneDrive\Coding\python\logger\file.py", line 3, in <module>
log = logger.Logger('logfile', 'file')
AttributeError: partially initialized module 'logger' has no attribute 'Logger' (most likely due to a circular import)
Is there a way to get the global variables with open(...) or something like that?
There are two solutions to this. One is to take the global variables out of file and move them to a third file, say globals.py which can be imported by both.
In terms of accessing global variables by opening the file, you can try and parse the file yourself, or indeed use something like AST. I imagine though that the aforementioned technique will be adequate for your use case.
Related
This question already has answers here:
Circular import dependency in Python [duplicate]
(7 answers)
Closed last year.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Main\Programming\Python\Console\mod_project\auto_message_mod.py", line 5, in <module>
import mod
File "D:\Main\Programming\Python\Console\mod_project\mod.py", line 77, in <module>
main()
File "D:\Main\Programming\Python\Console\mod_project\mod.py", line 18, in main
main_program_menu()
File "D:\Main\Programming\Python\Console\mod_project\mod.py", line 36, in main_program_menu
auto.auto_message_tools()
AttributeError: partially initialized module 'auto_message_mod' has no attribute 'auto_message_tools' (most likely due to a circular import)
I keep getting these errors while I try to import the file call auto_message_mod.py into mod.py and in mod.py, I tried to call the function auto_message_tools(these files are in the same folder). I also have imported the other files into mod.py and it worked perfectly. Except auto_message_mod.py. I have written import auto_message_mod as auto but it was not working. I have already tried auto.auto_message_tools() but didn't work. Can someone please help me?
Python is a scripting language, which is interpreted line by line. An import statement literally means that it will jump into that file and start reading over it, before jumping back to the original file and continuing to read through that. Read more here.
You can see that in your traceback, you import a file, which then calls a function that is presumably in the original.
The best way to fix this is to separate import-time code from run-time code. That means everything should import before the code is run, meaning all your code outside your main file should be only found within functions and classes. That means that you are much less likely to create a circular import like this, since all the code will already be initialised before you call any of it.
If that doesn't work, experimenting with moving culprit import statements to the bottom often helps, although it is stylistically bad, so I'd only use it as a last resort.
Let me first establish what working scenario.
main.py
module/file1.py
module/file2.py
main.py
import module.file1
print(module.file1)
module/file1.py
import module.file2
module/file2.py
import module.file1
Running python3 main.py gives me the following, which is fine.
<module 'module.file1' from '/project/module/file1.py'>
Now, if I change module/file2.py to have the following:
import module.file1 as testtt
I get this new output (error):
Traceback (most recent call last):
File "main.py", line 1, in <module>
import module.file1
File "/project/module/file1.py", line 1, in <module>
import module.file2
File "/project/module/file2.py", line 2, in <module>
import module.file1 as testtt
AttributeError: module 'module' has no attribute 'file2'
I'm guessing that python doesn't fully evaluate the imported module when simply importing, causing the circular reference to blow up only when you immediately use it within either of the two files.
I'd imagine I also would not get the error if I used the module in a function, since that would be evaluate when the function is actually called, like this:
import module.file1
def test():
print(module.file1)
What is the recommendation here? Should I just work to remove the circular reference? It seems like code smell anyway (existing code base).
Its an implementation detail. The import statement uses the __import__ function to do the work of finding and importing the module and then binds its returned module to the as testtt variable.
When doing a nested import like import module.file1 as testtt, __import__ returns the base module ("module"). Since the importer still needs to bind "file1" to the local namespace, it has to look up the submodule name "file1" on that object. Since the import of file1 is still in progress, it hasn't been bound to the "module" module yet.
It works in the import module.file1 case because file1 isn't bound to the local namespace and doesn't need a lookup.
There are many pitfalls with circular imports that will bedevil you throughout your code's life cycle. Good luck!
"import" is an executable statement, so you can just do the import inside the function
def test():
import module.file1
print(module.file1)
Now I want to built a function get_doc( ) which can get the doc of the module
Here's the code
def get_doc(module):
exec "import module"
print module.__doc__
And the information returned:
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
get_doc(sys)
NameError: name 'sys' is not defined
The problem is you're importing "module" instead of the specified module, and you didn't put the name module anywhere. A stupid fix to this would be to always using exec
def get_doc(module):
exec "import {}".format(module)
exec "print {}.__doc__".format(module)"
But instead of exec, i would advise you to use the __import__ function:
def get_doc(module):
module = __import__(module)
print module.__doc__
Which allows more flexibility, and you can modify, use module as you wanted.
When you say
get_doc(sys)
python will not be able to recognize sys. The actual way to do what you are trying to do would be to
pass the module name as a string parameter
use __import__ function to load the module, like this
def get_doc(module):
mod = __import__(module)
print mod.__doc__
get_doc("sys")
Note: I am not in favor of executing dynamic code in programs, but if you must use exec to solve this problem read this and have a basic understanding about the security implications and then look at aIKid's solution.
I have a segmenting.py module in a package called processing.
I am trying to call a function in the module in my main. It is extremely simple.
In main.py
from processing import segmenting
segmenting.test()
In segmenting.py
def test():
print 'succeed'
However, I end up with errors as follows:
>>> from processing import segmenting
>>>
>>> segmenting.test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'test'
>>>
Where went wrong?
The most likely cause is that you didn't restart your interactive interpreter after editing (and saving!) segmenting.py. Modules are imported only once and cached. If you edit the source code and then run the import statement again, the module is simply retrieved from the cache and doesn't pick up your changes. See also the reload() built-in.
PyRun_String("random.randint(1,10)", Py_eval_input, globals, globals);
returns error with:
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'random' is not defined
earlier in the code, I did:
PyImport_ImportModule("random");
I guess this is not the way to get it work. What is the correct way?
Thank you!
PyImport_ImportModule returns the imported value. You need to save it in globals under the name random. In summary:
PyMapping_SetItemString(globals, "random", PyImport_ImportModule("random"));
but don't forget to also check the result of the import in case it throws an exception.