I am working with a set of Manim projects and my project directory tree looks like this:
ManimProjects
(root directory)
public
(contains libraries shared by all projects)
public_mobjects.py
Project1
scene.py
Project2
scene.py
So, for example, in Project1
's scene.py
, I would like to import the public_mobjects
model, what should I do?
I have tried using from ..public.public_mobjects import ...
, which is the standard relative import syntax in Python. but this results in an error:
Manim Community v0.19.0
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "<user-dir>\AppData\Local\Programs\Python\Python313\Scripts\manim.exe\__main__.py", line 7, in <module>
sys.exit(main())
~~~~^^
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\click\core.py", line 1161, in __call__
return self.main(*args, **kwargs)
~~~~~~~~~^^^^^^^^^^^^^^^^^
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\click\core.py", line 1082, in main
rv = self.invoke(ctx)
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\click\core.py", line 1697, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\click\core.py", line 1443, in invoke
return ctx.invoke(self.callback, **ctx.params)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\click\core.py", line 788, in invoke
return __callback(*args, **kwargs)
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\manim\cli\render\commands.py", line 121, in render
for SceneClass in scene_classes_from_file(file):
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\manim\utils\module_ops.py", line 167, in scene_classes_from_file
module = get_module(file_path)
File "<user-dir>\AppData\Local\Programs\Python\Python313\Lib\site-packages\manim\utils\module_ops.py", line 67, in get_module
spec.loader.exec_module(module)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "<frozen importlib._bootstrap_external>", line 1026, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "<outer-dir-of-manim-projects>\ManimProjects\CircleOfFifth\scene.manim.py", line 40, in <module>
from ..public.text_config import *
ModuleNotFoundError: No module named 'd:\\'
I know that when direcly running a python code file, when relative import is used I will need py -m ...
to resolve relative imports, but manim doesnot run a python file directly. So what is the correct method of doing that in Manim?
Currently I program with Manim in VSCode with the "Manim Sideview" plugin. My Python version is 3.13.1
and Manim version 0.19.0
.
If you don't want to restructure your project, or edit $PYTHONPATH
, or edit sys.path
by hand, or edit __package__
, or attempt adding __init__.py
you could try solving the problem by using a tool meant to solve relative imports.
Here is one such tool $ pip install importmonkey
and then you can do this:
# =============== example structure ===============
├─ src
│ └─ project
│ └─ mymodule.py
└─ test
└─ test.py
# =============== importing in test.py ===============
from importmonkey import add_path
add_path("../src/project") # relative to current __file__
import mymodule
# add as many paths as needed, absolute or relative
# unix path conventions work so you can use '..' and '.'
# add_path validates the paths and returns added path as string
The issue happens because relative imports in Python depend on the __package__
attribute, which is typically set when running a module within a package using python -m package.module
However, Manim executes scripts differently—it loads them dynamically via importlib, causing relative imports (from ..public import public_mobjects) to fail.
Additionally, sys.path (which Python uses to search for modules) does not automatically include sibling directories, meaning Project1/scene.py cannot naturally import public/public_mobjects.py.
The proposed solution avoids modifying Python’s default import system (i.e., no changes to PYTHONPATH, or package structure). It instead dynamically adds directories to Python’s import path
Disclosure: I am the author of importmonkey.