I am working with a set of Manim projects and my project directory tree looks like this:
- (dir)
ManimProjects
(root directory)- (dir)
public
(contains libraries shared by all projects)- (file)
public_mobjects.py
- (file)
- (dir)
Project1
- (file)
scene.py
- (file)
- (dir)
Project2
- (file)
scene.py
- (file)
- (dir)
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_ctxmand.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
.
I am working with a set of Manim projects and my project directory tree looks like this:
- (dir)
ManimProjects
(root directory)- (dir)
public
(contains libraries shared by all projects)- (file)
public_mobjects.py
- (file)
- (dir)
Project1
- (file)
scene.py
- (file)
- (dir)
Project2
- (file)
scene.py
- (file)
- (dir)
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
.
1 Answer
Reset to default 0If 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
Why the Problem Occurs
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.
How the Solution Works
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.