Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi,
I'm trying to import dynamically import python files in a directory.
For example if the directory is:
utility ------init.py ------file1.py ------file2.py ------file3.py
The code to import them would be
from utility import file1 from utility import file2 from utility import file3
I want this line of code to be executed dynamically. So if I add a file4.py, I don't want to write from utility import import file4. That's why I want them to import dynamically.
file4.py
from utility import import file4
However, my code below gives an error of ImportError: cannot import name 'filename' where it treats the filename as an actual string and not as a variable.
ImportError: cannot import name 'filename'
Is there a way around this?
Here is the current code:
import utility for f in files: if f.endswith(".py") and not f.startswith('__init__'): filename = f.split('.') from utility import filename[0]
P.S. There are some solutions in the stack overflow like this one: https://stackoverflow.com/questions/1057431/how-to-load-all-modules-in-a-folder
But again, it requires to be executed every time I add a python file in the directory (i.e. no dynamic)
for clarification: I think you do not actually mean importing modules dynamically (which would imply importing them on a "as needed basis" depending on the branching of your code. From what I do understand you want to implicitly import all modules located in a package (folder). I assume you are aware that python has the wildcard syntax for that.
from package import a, b, c, d # is equivalent to (assuming there is only a, b, c, d) from package import *
To make this somewhat useful you will have to define in your __init__.py what you want to be imported (as described in your linked post).
__init__.py
However to import from packages Python has to know where to look for them. If you have your folder utility in your c4d plugin folder, this won't work out of the box. There are multiple ways to achieve this and people will probably boo me for telling you this, but the easiest way is to just add to (or pollute as some people would say) the sys path.
utility
_path = os.path.dirname(__file__) if _path not in sys.path: sys.path.insert(0, _path) #assuming foo is a folder/package in the dir of __file__ from foo import bar
One of the drawbacks is that you have to do this:
_path = os.path.dirname(__file__) if _path not in sys.path: sys.path.insert(0, _path) from foo import bar if SOME_SORT_OF_DEBUG_CONDITION_IS_TRUE: reload(bar)
If you want to reload that module on a running Python VM. For example when you hit "reload python plugins" in c4d. Otherwise you have to restart c4d for each code change to apply.
Cheers zipit
@zipit Thanks for the response. Yes, I ended up "polluting" the sys.path. I don't mind though. It works as expected. Here is the working code for me without using the __init__ file and it imports dynamically.
__init__
import c4d import os import sys rigDir = "C:/Users/Luke/Dropbox/Scripts/c4d" if not rigDir in sys.path: sys.path.append(rigDir) dir_path = "C:/Users/Luke/Dropbox/Scripts/c4d/utility" files = os.listdir(dir_path) import utility from utility import hello_world for f in files: if f.endswith(".py") and not f.startswith('__init__'): filename = f.split('.') #from utility import filename[0] exec('from utility import %s' % filename[0]) exec('reload(%s)'% filename[0])
The only caveat so far is to convert all scripts to
if __name__=='__main__': main()
Because at this point, all scripts get executed when imported hahaha. Should have listed to everyone telling me to use the if __name__=='__main__' from the start.
if __name__=='__main__'
Hi @bentraje,
While @zipit has almost said everything I would like to add few things:
Cheers, Maxime.
@m_adam
Thanks for the additional insight and the related links. Appreciate it a lot.