Pyinstaller IntFlag、vcruntime140.dll及pyttsx3错误的解决办法

在打包程序的时候遇到一大堆报错,查了许久的资料,终于解决.现在整理一下备查.

注:以下内容均来自谷歌,由笔者整理

  • enum.IntFlag

使用pyinstaller编译程序时出现以下错误

...
...
    class RegexFlag(enum.IntFlag):
AttributeError: module 'enum' has no attribute 'IntFlag'

出现原因: 与tensorflow的enum34库冲突,卸载即可,在需要时再重装

解决办法:

pip uninstall enum34
  • vcruntime140.dll

运行程序时出现vcruntime140.dll与系统不兼容的错误

解决办法:关闭upx,在指令中添加如下语句

--noupx
  • pyttsx3

这是问题最多的地方
编译使用了pyttsx3的程序后,运行会出现如下错误

ModuleNotFoundError: No module named 'pyttsx3.drivers'

解决办法:
在被编译的程序的目录下(理论上任何目录都行)新建目录并新建文件“hook-pyttsx3.py”
(我这里新建“hooks\hook-pyttsx3.py”)
内容如下:

#-----------------------------------------------------------------------------
# Copyright (c) 2013-2017, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------


"""
pyttsx3 imports drivers module based on specific platform.
Fount at https://github.com/nateshmbhat/pyttsx3/issues/6
"""


hiddenimports = [
    'pyttsx3.drivers',
    'pyttsx3.drivers.dummy',
    'pyttsx3.drivers.espeak',
    'pyttsx3.drivers.nsss',
    'pyttsx3.drivers.sapi5',
]

再在命令行中添加如下参数:
(我在被编译程序根目录执行的pyinstaller,所以用的相对路径“hooks”)

--additional-hooks-dir hooks

此时再编译运行出现错误:

pywintypes.com_error: (-2147352573, '找不到成员。', None, None)

解决办法:
修改文件“<python路径>\Lib\site-packages\PyInstaller\loader\rthooks\pyi_rth_win32comgenpy.py”
(请阅读后续部分进行操作)
最终效果:

#-----------------------------------------------------------------------------
# Copyright (c) 2013-2017, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------


# The win32.client.gencache code must be allowed to create the cache in %temp%
# (user's temp). It is necessary to get the gencache code to use a suitable
# directory other than the default in lib\site-packages\win32com\client\gen_py.
# PyInstaller does not provide this directory structure and the frozen
# executable could be placed in a non-writable directory like 'C:\Program Files.
# That's the reason for %temp% directory.
#
# http://www.py2exe.org/index.cgi/UsingEnsureDispatch

import sys
# The win32com fixes aren't needed for Python 3.X
if sys.version_info >= (3, 0):
    pass
else:
    import atexit
    import os
    import shutil
    import tempfile


    # Put gen_py cache in temp directory.
    supportdir = tempfile.mkdtemp()
    # gen_py has to be put into directory 'gen_py'.
    genpydir = os.path.join(supportdir, 'gen_py')


    # Create 'gen_py' directory. This directory does not need
    # to contain '__init__.py' file.
    try:
        # win32com gencache cannot be put directly to 'supportdir' with any
        # random name. It has to be put in a directory called 'gen_py'.
        # This is the reason why to create this directory in supportdir'.
        os.makedirs(genpydir)
        # Remove temp directory at application exit and ignore any errors.
        atexit.register(shutil.rmtree, supportdir, ignore_errors=True)
    except OSError:
        pass


    # Override the default path to gen_py cache.
    import win32com
    win32com.__gen_path__ = genpydir


    # The attribute __loader__ makes module 'pkg_resources' working but On Windows
    # it breaks pywin32 (win32com) and test 'basic/test_pyttsx' will fail. Just
    # removing that attribute for win32com fixes that and gencache is created properly.
    if hasattr(win32com, '__loader__'):
        del win32com.__loader__


    # Ensure genpydir is in 'gen_py' module paths.
    import win32com.gen_py
    win32com.gen_py.__path__.insert(0, genpydir)

即在最前面添加版本判断,若python版本大于等于3.0,则不进行处理。后续pyinstaller可能会对该文件进行修改,不建议直接复制,手动添加如下内容即可:

import sys
# The win32com fixes aren't needed for Python 3.X
if sys.version_info >= (3, 0):
    pass
else:
<以下为原内容>
仅有 1 条评论
  1. 很棒 在看到这篇文章前一直在受苦 终于搞定了

添加新评论