Repository: ManimCommunity/manim

Issue:
TypeError: not all arguments converted during string formatting manim
This error occurs, when there is a logging report by manim that the partial movie directory is full. This message is formatted in such a way that it conflicts with the formatting that the logging package of python uses. If I remove the logging line 587 in scene_file_writer.py the error goes away.

I'm rather new to python and manim, it can be that I'm doing something stupid. 

```
Traceback (most recent call last):
╭──────────────────────────────────────────────────────────────────────────────────────╮
│ File "/home/jmartin/.local/lib/python3.8/site-packages/manim/cli/render/commands.py",│
│line 139, in render                                                                   │
│    136         for SceneClass in scene_classes_from_file(file):                      │
│    137             try:                                                              │
│    138                 scene = SceneClass()                                          │
│  ❱ 139                 scene.render()                                                │
│    140             except Exception:                                                 │
│    141                 error_console.print_exception()                               │
│    142                 sys.exit(1)                                                   │
│ File "/home/jmartin/.local/lib/python3.8/site-packages/manim/scene/scene.py", line   │
│225, in render                                                                        │
│     222             return True                                                      │
│     223         self.tear_down()                                                     │
│     224         # We have to reset these settings in case of multiple renders.       │
│  ❱  225         self.renderer.scene_finished(self)                                   │
│     226                                                                              │
│     227         # Show info only if animations are rendered or to get image          │
│     228         if (                                                                 │
│ File                                                                                 │
│"/home/jmartin/.local/lib/python3.8/site-packages/manim/renderer/cairo_renderer.py",  │
│line 287, in scene_finished                                                           │
│    284     def scene_finished(self, scene):                                          │
│    285         # If no animations in scene, render an image instead                  │
│    286         if self.num_plays:                                                    │
│  ❱ 287             self.file_writer.finish()                                         │
│    288         elif config.write_to_movie:                                           │
│    289             config.save_last_frame = True                                     │
│    290             config.write_to_movie = False                                     │
│ File                                                                                 │
│"/home/jmartin/.local/lib/python3.8/site-packages/manim/scene/scene_file_writer.py",  │
│line 362, in finish                                                                   │
│    359             if config["flush_cache"]:                                         │
│    360                 self.flush_cache_directory()                                  │
│    361             else:                                                             │
│  ❱ 362                 self.clean_cache()                                            │
│    363         elif is_png_format() and not config["dry_run"]:                       │
│    364             target_dir, _ = os.path.splitext(self.image_file_path)            │
│    365             logger.info("\n%i images ready at %s\n", self.frame_count, target_│
│ File                                                                                 │
│"/home/jmartin/.local/lib/python3.8/site-packages/manim/scene/scene_file_writer.py",  │
│line 587, in clean_cache                                                              │
│    584             # oldest_file_path = min(cached_partial_movies, key=os.path.getati│
│    585             for file_to_delete in oldest_files_to_delete:                     │
│    586                 os.remove(file_to_delete)                                     │
│  ❱ 587             logger.info(                                                      │
│    588                 f"The partial movie directory is full (> {config['max_files_ca│
│    589                 "You can change this behaviour by changing max_files_cached in│
│    590             )                                                                 │
│ File "/usr/lib/python3.8/logging/__init__.py", line 1446, in info                    │
│    1443         logger.info("Houston, we have a %s", "interesting problem", exc_info=│
│    1444         """                                                                  │
│    1445         if self.isEnabledFor(INFO):                                          │
│  ❱ 1446             self._log(INFO, msg, args, **kwargs)                             │
│    1447                                                                              │
│    1448     def warning(self, msg, *args, **kwargs):                                 │
│    1449         """                                                                  │
│ File "/usr/lib/python3.8/logging/__init__.py", line 1589, in _log                    │
│    1586                 exc_info = sys.exc_info()                                    │
│    1587         record = self.makeRecord(self.name, level, fn, lno, msg, args,       │
│    1588                                  exc_info, func, extra, sinfo)               │
│  ❱ 1589         self.handle(record)                                                  │
│    1590                                                                              │
│    1591     def handle(self, record):                                                │
│    1592         """                                                                  │
│ File "/usr/lib/python3.8/logging/__init__.py", line 1599, in handle                  │
│    1596         well as those created locally. Logger-level filtering is applied.    │
│    1597         """                                                                  │
│    1598         if (not self.disabled) and self.filter(record):                      │
│  ❱ 1599             self.callHandlers(record)                                        │
│    1600                                                                              │
│    1601     def addHandler(self, hdlr):                                              │
│    1602         """                                                                  │
│ File "/usr/lib/python3.8/logging/__init__.py", line 1661, in callHandlers            │
│    1658             for hdlr in c.handlers:                                          │
│    1659                 found = found + 1                                            │
│    1660                 if record.levelno >= hdlr.level:                             │
│  ❱ 1661                     hdlr.handle(record)                                      │
│    1662             if not c.propagate:                                              │
│    1663                 c = None    #break out                                       │
│    1664             else:                                                            │
│ File "/usr/lib/python3.8/logging/__init__.py", line 954, in handle                   │
│     951         if rv:                                                               │
│     952             self.acquire()                                                   │
│     953             try:                                                             │
│  ❱  954                 self.emit(record)                                            │
│     955             finally:                                                         │
│     956                 self.release()                                               │
│     957         return rv                                                            │
│ File "/home/jmartin/.local/lib/python3.8/site-packages/rich/logging.py", line 72, in │
│emit                                                                                  │
│     69         """Invoked by logging."""                                             │
│     70         path = Path(record.pathname).name                                     │
│     71         log_style = f"logging.level.{record.levelname.lower()}"               │
│  ❱  72         message = self.format(record)                                         │
│     73         time_format = None if self.formatter is None else self.formatter.datef│
│     74         log_time = datetime.fromtimestamp(record.created)                     │
│     75                                                                               │
│ File "/usr/lib/python3.8/logging/__init__.py", line 929, in format                   │
│     926             fmt = self.formatter                                             │
│     927         else:                                                                │
│     928             fmt = _defaultFormatter                                          │
│  ❱  929         return fmt.format(record)                                            │
│     930                                                                              │
│     931     def emit(self, record):                                                  │
│     932         """                                                                  │
│ File "/usr/lib/python3.8/logging/__init__.py", line 668, in format                   │
│     665         called to format the event time. If there is exception information,  │
│     666         it is formatted using formatException() and appended to the message. │
│     667         """                                                                  │
│  ❱  668         record.message = record.getMessage()                                 │
│     669         if self.usesTime():                                                  │
│     670             record.asctime = self.formatTime(record, self.datefmt)           │
│     671         s = self.formatMessage(record)                                       │
│ File "/usr/lib/python3.8/logging/__init__.py", line 373, in getMessage               │
│     370         """                                                                  │
│     371         msg = str(self.msg)                                                  │
│     372         if self.args:                                                        │
│  ❱  373             msg = msg % self.args                                            │
│     374         return msg                                                           │
│     375                                                                              │
│     376 #                                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────╯
TypeError: not all arguments converted during string formatting

```



Discussion:
Thank you for reporting this, can you share the scene you are running please and the command you are running it with? Is that the full logs in the attached? I might be wrong but the stacktrace seems incomplete? Also when creating an issue there is an area in the template you can paste logs so people can view the logs without needing to download any files. 
The error is not reproducible with a certain scene. It arises only, when the partial move directory is full. Then it is also thrown, when I start a Scene that just writes a word or draws a circle. I will post the stacktrace again to the correct formatting.

And also, I can easily fix it by removing line 587 in the file scene_file_writer.py. But this is maybe not the best way to do it

Resolving patch:
diff --git a/manim/scene/scene_file_writer.py b/manim/scene/scene_file_writer.py
--- a/manim/scene/scene_file_writer.py
+++ b/manim/scene/scene_file_writer.py
@@ -585,7 +585,7 @@ def clean_cache(self):
             for file_to_delete in oldest_files_to_delete:
                 os.remove(file_to_delete)
             logger.info(
-                f"The partial movie directory is full (> {config['max_files_cached']} files). Therefore, manim has removed the {number_files_to_delete} oldest file(s).",
+                f"The partial movie directory is full (> {config['max_files_cached']} files). Therefore, manim has removed the {number_files_to_delete} oldest file(s)."
                 "You can change this behaviour by changing max_files_cached in config.",
             )
 


Test patch: