Python 3.8+moviepy报错:TypeError: ‘module‘ object is not callable

☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython

一、引言

最近有博友在博文《 https://blog.csdn.net/LaoYuanPython/article/details/105346224 moviepy应用pyinstaller打包后执行报错AttributeError: module audio/video.fx.all has no attribute ‘fadein’、crop》评论区留言,反映使用该文以及《https://blog.csdn.net/LaoYuanPython/article/details/106133649 关于moviepy打包报错AttributeError: module audio/video.fx.all has no attribute fadein、crop文章的纠错和抄袭》介绍的解决方案后执行resize函数报错:
在这里插入图片描述
老猿进行测试,发现以前执行通过的老代码(在Python3.7.4)在现在Python3.8.5环境下确实存在问题,不只是resize,所有通过上文中介绍的方式导入的函数都有问题,如执行crop:
在这里插入图片描述

Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> from  moviepy.editor import *

>>> clipVideo = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4")
>>> clipVideo.crop(0,260)
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    clipVideo.crop(0,260)
TypeError: 'module' object is not callable
>>>

二、解决办法

相关错是因为moviepy包下子包audio.fx.all、video.fx.all对应的目录moviepy\audio\fx\all、moviepy\video\fx\all下的包文件__init__.py中,分别使用了如下的方式import模块:
audio.fx.all子包

import pkgutil

import moviepy.audio.fx as fx

__all__ = [name for _, name, _ in pkgutil.iter_modules(
    fx.__path__) if name != "all"]

for name in __all__:
    exec("from ..%s import %s" % (name, name))

video.fx.all子包

import pkgutil

import moviepy.video.fx as fx

__all__ = [name for _, name, _ in pkgutil.iter_modules(
    fx.__path__) if name != "all"]

for name in __all__:
    exec("from ..%s import %s" % (name, name))

可以看到这两个子包使用的是一种动态加载模块的模式加载包下的模块的,pyinstaller对这种模式不能处理。

解决办法:
1、将这2个__init__.py文件的上面所列最后两行注释掉;
2、在Python中将上述注释掉两行代码后前面的内容复制后加一个如下输出语句的代码:

for name in __all__: 
	print("from ..%s import %s" % (name, name))

如针对video.fx.all,在Python中手工执行如下代码:

import pkgutil

import moviepy.video.fx as fx

__all__ = [name for _, name, _ in pkgutil.iter_modules(
    fx.__path__) if name != "all"]
for name in __all__: 
	print("from ..%s import %s" % (name, name))

输出如下:
在这里插入图片描述

将下面的输出语句拷贝到video.fx.all的__init__.py,替换被注释的2行代码即可,最后完整的文件内容如下:


"""
Loads all the fx !
Usage:
import moviepy.video.fx.all as vfx
clip = vfx.resize(some_clip, width=400)
clip = vfx.mirror_x(some_clip)
"""

import pkgutil

import moviepy.video.fx as fx

__all__ = [name for _, name, _ in pkgutil.iter_modules(
    fx.__path__) if name != "all"]

#for name in __all__:
#	    exec("from ..%s import %s" % (name, name))
#for name in __all__: 
	#print("from  moviepy.video.fx import %s" % (name))
    #print(("from ..%s import %s" % (name, name)))

from ..accel_decel import accel_decel
from ..blackwhite import blackwhite
from ..blink import blink
from ..colorx import colorx
from ..crop import crop
from ..even_size import even_size
from ..fadein import fadein
from ..fadeout import fadeout
from ..freeze import freeze
from ..freeze_region import freeze_region
from ..gamma_corr import gamma_corr
from ..headblur import headblur
from ..invert_colors import invert_colors
from ..loop import loop
from ..lum_contrast import lum_contrast
from ..make_loopable import make_loopable
from ..margin import margin
from ..mask_and import mask_and
from ..mask_color import mask_color
from ..mask_or import mask_or
from ..mirror_x import mirror_x
from ..mirror_y import mirror_y
from ..painting import painting
from ..resize import resize
from ..rotate import rotate
from ..scroll import scroll
from ..speedx import speedx
from ..supersample import supersample
from ..time_mirror import time_mirror
from ..time_symmetrize import time_symmetrize

同样对moviepy\audio\fx\all下的包文件__init__.py进行类似处理。这样处理后,再重新打包就可以解决掉该问题。

上述处理过程如果担心破坏原始的moviepy包,可以将python目录下的moviepy包拷贝一份到对应代码目录下再修改更好。

同样方式修改audio.fx.all的__init__.py,最后得到的__init__.py文件内容如下:

"""
Loads all the fx !
Usage:
import moviepy.audio.fx.all as afx
audio_clip = afx.volume_x(some_clip, .5)
"""

import pkgutil

import moviepy.audio.fx as fx

__all__ = [name for _, name, _ in pkgutil.iter_modules(
    fx.__path__) if name != "all"]

#for name in __all__:
#    exec("from ..%s import %s" % (name, name))
#for name in __all__: 
	#print("from  moviepy.audio.fx import %s" % (name))
	#print("from ..%s import %s" % (name, name))

from ..audio_fadein import audio_fadein
from ..audio_fadeout import audio_fadeout
from ..audio_left_right import audio_left_right
from ..audio_loop import audio_loop
from ..audio_normalize import audio_normalize
from ..volumex import volumex

问题即可解决。

三、后记

虽然通过这种方式解决了问题,但老猿目前并没有想明白这其中的原因,原方式在Python3.7.4的版本中没有问题,且在3.8.5环境下加载没有报错,手工执行相关代码函数能正常导入,具体原因有时间再深入分析。

四、小结

本节介绍了moviepy打包报错原有《 https://blog.csdn.net/LaoYuanPython/article/details/105346224 moviepy应用pyinstaller打包后执行报错AttributeError: module audio/video.fx.all has no attribute ‘fadein’、crop》中的解决办法存在Python3.8.5的环境下的TypeError: 'module' object is not callable问题,以及更新的解决办法。

更多moviepy的介绍请参考《PyQt+moviepy音视频剪辑实战文章目录》或《moviepy音视频开发专栏》。

写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

如果对文章内容存在疑问,可以在博客评论区留言,或关注:老猿Python 微信公号发消息咨询。

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython

猜你喜欢

转载自blog.csdn.net/LaoYuanPython/article/details/114385758