SOLVED Dynamically Import All Python Files


I'm trying to import dynamically import python files in a directory.

For example if the directory is:


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, I don't want to write from utility import import file4. That's why I want them to import dynamically.

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.

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:

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 what you want to be imported (as described in your linked post).

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.

_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 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.


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.

import c4d
import os
import sys

rigDir = "C:/Users/Luke/Dropbox/Scripts/c4d"
if not rigDir in sys.path:

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__':

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.

Hi @bentraje,

While @zipit has almost said everything I would like to add few things:

  • if __name__=='__main__' is really needed since its ensure that your code is not called from anywhere, performance-wise its also very important, even if it's not a big issue in your plugin logic if your code is executed each time you import stuff, think to the user and his performance.
  • It's recommended to do local import and not global import (as you do) since if you add a module named xyz to the sys.path from your plugin A and from plugin B you try to import another module named xyz, it will load the one from plugin A (the first one register). And the other plugin will not work. For more information read Best Practise for import and especially the great localimport module from @NiklasR that is mentioned in the Best Practise for Import topic



Thanks for the additional insight and the related links. Appreciate it a lot.