从使用 Tix 的 Python 代码生成 .exe 文件

Generating .exe file from Python code that uses Tix

最近我在 Github 上发现了一个我经常使用的程序代码 (Pikasav),并且由于我最近学习了 Python 语法,所以决定将其 fork 以练习 Python 和实施一些可以使其 easier/better 使用的功能。

实现功能后,我尝试使用 py2exe 生成 .exe 文件,但没有成功,因为找不到 Tix 模块。我尝试将 Tix.py 复制到我的工作目录中,它也没有用。

在那之后,我决定尝试 PyInstaller,因为我认为我在 setup.py 文件中向 py2exe 传递参数时做错了什么,而且它似乎更容易使用。然而,它也没有工作,因为同样的原因,这显然意味着问题不是来自 py2exe 配置。

这是 PyInstaller 的输出,虽然我认为它不会那么有用:

C:\Users\Afonso\Documents\Side Projects\PikaSav>PyInstaller --onefile pikasav.py
1421 INFO: PyInstaller: 3.1.1
1421 INFO: Python: 2.7.11
1421 INFO: Platform: Windows-10-10.0.10240
1421 INFO: wrote C:\Users\Afonso\Documents\Side Projects\PikaSav\pikasav.spec
1421 INFO: UPX is not available.
1437 INFO: Extending PYTHONPATH with paths
['C:\Users\Afonso\Documents\Side Projects\PikaSav',
 'C:\Users\Afonso\Documents\Side Projects\PikaSav']
1437 INFO: checking Analysis
1437 INFO: Building Analysis because out00-Analysis.toc is non existent
1437 INFO: Initializing module dependency graph...
1452 INFO: Initializing module graph hooks...
1530 INFO: running Analysis out00-Analysis.toc
1657 INFO: Adding Microsoft.VC90.CRT to dependent assemblies of final executable
  required by C:\Python27\python.exe
1780 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_60a5df56e60dc5df.manifest
1796 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_8550c6b5d18a9128.manifest
1796 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_f47f259ef656232a.manifest
1873 INFO: Searching for assembly x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.9158_none ...
1873 INFO: Found manifest C:\WINDOWS\WinSxS\Manifests\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_5091b51ebcb97cdc.manifest
1889 INFO: Searching for file msvcr90.dll
1889 INFO: Found file C:\WINDOWS\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_5091b51ebcb97cdc\msvcr90.dll
1889 INFO: Searching for file msvcp90.dll
1889 INFO: Found file C:\WINDOWS\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_5091b51ebcb97cdc\msvcp90.dll
1889 INFO: Searching for file msvcm90.dll
1889 INFO: Found file C:\WINDOWS\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_5091b51ebcb97cdc\msvcm90.dll
1967 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_60a5df56e60dc5df.manifest
1967 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_8550c6b5d18a9128.manifest
1967 INFO: Found C:\WINDOWS\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9158_none_f47f259ef656232a.manifest
1967 INFO: Adding redirect Microsoft.VC90.CRT version (9, 0, 21022, 8) -> (9, 0, 30729, 9158)
2514 INFO: Analyzing C:\Users\Afonso\Documents\Side Projects\PikaSav\pikasav.py
4889 INFO: Looking for import hooks ...
4905 INFO: Processing hook   hook-_tkinter.py
5077 INFO: checking Tree
5077 INFO: Building Tree because out00-Tree.toc is non existent
5092 INFO: Building Tree out00-Tree.toc
5338 INFO: checking Tree
5338 INFO: Building Tree because out01-Tree.toc is non existent
5339 INFO: Building Tree out01-Tree.toc
5389 INFO: Processing hook   hook-encodings.py
7202 INFO: Looking for ctypes DLLs
7202 INFO: Analyzing run-time hooks ...
7202 INFO: Including run-time hook 'pyi_rth__tkinter.py'
7217 INFO: Looking for dynamic libraries
7530 INFO: Looking for eggs
7530 INFO: Using Python library C:\WINDOWS\system32\python27.dll
7530 INFO: Found binding redirects:
[BindingRedirect(name=u'Microsoft.VC90.CRT', language=None, arch=u'x86', oldVersion=(9, 0, 21022, 8), newVersion=(9, 0, 30729, 9158), publicKeyToken=u'1fc8b3b9a1e18e3b')]
7546 INFO: Warnings written to C:\Users\Afonso\Documents\Side Projects\PikaSav\build\pikasav\warnpikasav.txt
7827 INFO: checking PYZ
7827 INFO: Building PYZ because out00-PYZ.toc is non existent
7827 INFO: Building PYZ (ZlibArchive) C:\Users\Afonso\Documents\Side Projects\PikaSav\build\pikasav\out00-PYZ.pyz
8062 INFO: checking PKG
8062 INFO: Building PKG because out00-PKG.toc is non existent
8062 INFO: Building PKG (CArchive) out00-PKG.pkg
8280 INFO: Redirecting Microsoft.VC90.CRT version (9, 0, 21022, 8) -> (9, 0, 30729, 9158)
16608 INFO: Bootloader C:\Python27\lib\site-packages\pyinstaller-3.1.1-py2.7.egg\PyInstaller\bootloader\Windows-32bit\run.exe
16608 INFO: checking EXE
16608 INFO: Building EXE because out00-EXE.toc is non existent
16608 INFO: Building EXE from out00-EXE.toc
16702 INFO: Appending archive to EXE C:\Users\Afonso\Documents\Side Projects\PikaSav\dist\pikasav.exe

这里是 warnpikasav.txt 内容,在上面的输出中提到。

missing module named unicodedata.ucd_3_2_0 - imported by unicodedata, stringprep, encodings.idna
missing module named _sre.MAXREPEAT - imported by _sre, sre_constants
missing module named _warnings.warn_explicit - imported by _warnings, warnings
missing module named _warnings.filters - imported by _warnings, warnings
missing module named _warnings.once_registry - imported by _warnings, warnings
missing module named _warnings.default_action - imported by _warnings, warnings
missing module named _warnings.warn - imported by _warnings, warnings
missing module named strop.whitespace - imported by strop, string
missing module named strop.maketrans - imported by strop, string
missing module named strop.lowercase - imported by strop, string
missing module named strop.uppercase - imported by strop, string
missing module named itertools.islice - imported by itertools, repr, heapq
missing module named itertools.starmap - imported by itertools, collections
missing module named itertools.repeat - imported by itertools, collections
missing module named itertools.imap - imported by itertools, heapq, collections
missing module named itertools.tee - imported by itertools, heapq
missing module named itertools.izip - imported by itertools, heapq
missing module named itertools.count - imported by itertools, heapq, threading
missing module named itertools.chain - imported by itertools, tokenize, heapq, collections
missing module named org.PyStringMap - imported by org, copy
missing module named org - imported by copy
missing module named exceptions.ReferenceError - imported by exceptions, weakref
missing module named _weakref.ref - imported by _weakref, _weakrefset, weakref
missing module named _weakref.ReferenceType - imported by _weakref, weakref
missing module named _weakref.proxy - imported by _weakref, weakref
missing module named _weakref.getweakrefs - imported by _weakref, weakref
missing module named _weakref.getweakrefcount - imported by _weakref, weakref
missing module named _weakref.ProxyType - imported by _weakref, weakref
missing module named _weakref.CallableProxyType - imported by _weakref, weakref
missing module named copy.deepcopy - imported by copy, weakref
missing module named re._compile - imported by re, sre
missing module named re.__all__ - imported by re, sre
missing module named codecs.mbcs_encode - imported by codecs, encodings.mbcs
missing module named codecs.mbcs_decode - imported by codecs, encodings.mbcs
missing module named binascii.b2a_qp - imported by binascii, quopri
missing module named binascii.a2b_qp - imported by binascii, quopri
missing module named binascii.a2b_uu - imported by binascii, encodings.uu_codec
missing module named binascii.b2a_uu - imported by binascii, encodings.uu_codec
missing module named binascii.hexlify - imported by binascii, random
missing module named errno.EINVAL - imported by errno, StringIO
missing module named errno.ENOENT - imported by errno, gettext
missing module named cStringIO.StringIO - imported by cStringIO, gettext, pprint, shlex, tempfile, pickle, encodings.uu_codec, quopri, encodings.quopri_codec
missing module named struct.calcsize - imported by struct, ctypes
missing module named _struct.__doc__ - imported by _struct, struct
missing module named _struct._clearcache - imported by _struct, struct
missing module named _subprocess.STD_OUTPUT_HANDLE - imported by _subprocess, subprocess
missing module named _subprocess.CREATE_NEW_PROCESS_GROUP - imported by _subprocess, subprocess
missing module named _subprocess.STD_INPUT_HANDLE - imported by _subprocess, subprocess
missing module named _subprocess.STARTF_USESHOWWINDOW - imported by _subprocess, subprocess
missing module named _subprocess.CREATE_NEW_CONSOLE - imported by _subprocess, subprocess
missing module named _subprocess.STD_ERROR_HANDLE - imported by _subprocess, subprocess
missing module named _subprocess.STARTF_USESTDHANDLES - imported by _subprocess, subprocess
missing module named _subprocess.SW_HIDE - imported by _subprocess, subprocess
missing module named collections.namedtuple - imported by collections, inspect, unittest.util, difflib, doctest
missing module named cPickle.loads - imported by cPickle, collections
missing module named cPickle.dumps - imported by cPickle, collections
missing module named thread.get_ident - imported by thread, collections
missing module named thread._local - imported by thread, threading
missing module named thread.stack_size - imported by thread, threading
missing module named thread.allocate_lock - imported by thread, _strptime
missing module named collections.deque - imported by collections, shlex, threading
missing module named collections.OrderedDict - imported by collections, unittest.util
missing module named operator.itemgetter - imported by operator, collections, heapq
missing module named operator.eq - imported by operator, collections
missing module named operator.attrgetter - imported by operator, inspect
missing module named _collections.deque - imported by _collections, collections
missing module named _collections.defaultdict - imported by _collections, collections
missing module named time.time - imported by time, threading
missing module named time.sleep - imported by time, threading
missing module named datetime.date - imported by datetime, _strptime
missing module named _functools.partial - imported by _functools, functools
missing module named _functools.reduce - imported by _functools, functools
missing module named _hashlib.pbkdf2_hmac - imported by _hashlib, hashlib
missing module named math.sin - imported by math, random
missing module named math.sqrt - imported by math, random
missing module named math.cos - imported by math, random
missing module named math.acos - imported by math, random
missing module named math.ceil - imported by math, random
missing module named math.exp - imported by math, random
missing module named math.log - imported by math, random
missing module named math.e - imported by math, random
missing module named math.pi - imported by math, random
missing module named _io.DEFAULT_BUFFER_SIZE - imported by _io, io
missing module named _io.BytesIO - imported by _io, io
missing module named _io.open - imported by _io, io
missing module named _io.BufferedWriter - imported by _io, io
missing module named _io.FileIO - imported by _io, io
missing module named _io.BlockingIOError - imported by _io, io
missing module named _io.IncrementalNewlineDecoder - imported by _io, io
missing module named _io.BufferedReader - imported by _io, io
missing module named _io.BufferedRandom - imported by _io, io
missing module named _io.StringIO - imported by _io, io
missing module named _io.BufferedRWPair - imported by _io, io
missing module named _io.TextIOWrapper - imported by _io, io
missing module named _io.UnsupportedOperation - imported by _io, io
missing module named readline - imported by cmd, pdb
missing module named 'org.python'.PyStringMap - imported by 'org.python', pickle
missing module named 'org.python' - imported by pickle
missing module named fcntl - imported by tempfile, subprocess
missing module named threading.RLock - imported by threading, _threading_local
missing module named threading.current_thread - imported by threading, _threading_local
missing module named os.urandom - imported by os, random
missing module named riscosenviron._Environ - imported by riscosenviron, os
missing module named riscosenviron - imported by os
missing module named riscospath - imported by os
missing module named riscos._exit - imported by riscos, os
missing module named riscos - imported by os
missing module named ce._exit - imported by ce, os
missing module named ce - imported by os
missing module named _emx_link.link - imported by _emx_link, os
missing module named _emx_link - imported by os
missing module named os2._exit - imported by os2, os
missing module named os2 - imported by os
missing module named nt._isdir - imported by nt, ntpath
missing module named nt._getfullpathname - imported by nt, ntpath
missing module named nt._exit - imported by nt, os
missing module named pwd - imported by posixpath
missing module named posix._exit - imported by posix, os
missing module named posix - imported by os
missing module named resource - imported by posix
missing module named _ctypes._wstring_at_addr - imported by _ctypes, ctypes
missing module named _ctypes._string_at_addr - imported by _ctypes, ctypes
missing module named _ctypes._cast_addr - imported by _ctypes, ctypes
missing module named _ctypes._memset_addr - imported by _ctypes, ctypes
missing module named _ctypes._memmove_addr - imported by _ctypes, ctypes
missing module named _ctypes.get_last_error - imported by _ctypes, ctypes
missing module named _ctypes.set_last_error - imported by _ctypes, ctypes
missing module named _ctypes._check_HRESULT - imported by _ctypes, ctypes
missing module named _ctypes.set_conversion_mode - imported by _ctypes, ctypes
missing module named _ctypes._pointer_type_cache - imported by _ctypes, ctypes
missing module named _ctypes.POINTER - imported by _ctypes, ctypes
missing module named _ctypes._SimpleCData - imported by _ctypes, ctypes
missing module named _ctypes.get_errno - imported by _ctypes, ctypes
missing module named _ctypes.set_errno - imported by _ctypes, ctypes
missing module named _ctypes.alignment - imported by _ctypes, ctypes
missing module named _ctypes.addressof - imported by _ctypes, ctypes
missing module named _ctypes.resize - imported by _ctypes, ctypes
missing module named _ctypes.byref - imported by _ctypes, ctypes
missing module named _ctypes.sizeof - imported by _ctypes, ctypes
missing module named _ctypes.dlopen - imported by _ctypes, ctypes
missing module named _ctypes.FUNCFLAG_STDCALL - imported by _ctypes, ctypes
missing module named _ctypes.LoadLibrary - imported by _ctypes, ctypes
missing module named _ctypes.FUNCFLAG_USE_ERRNO - imported by _ctypes, ctypes
missing module named _ctypes.FUNCFLAG_USE_LASTERROR - imported by _ctypes, ctypes
missing module named _ctypes.FUNCFLAG_PYTHONAPI - imported by _ctypes, ctypes
missing module named _ctypes.FUNCFLAG_CDECL - imported by _ctypes, ctypes
missing module named _ctypes.FormatError - imported by _ctypes, ctypes
missing module named _ctypes.ArgumentError - imported by _ctypes, ctypes
missing module named _ctypes.RTLD_LOCAL - imported by _ctypes, ctypes
missing module named _ctypes.RTLD_GLOBAL - imported by _ctypes, ctypes
missing module named _ctypes.__version__ - imported by _ctypes, ctypes
missing module named _ctypes.CFuncPtr - imported by _ctypes, ctypes
missing module named _ctypes._Pointer - imported by _ctypes, ctypes
missing module named _ctypes.Structure - imported by _ctypes, ctypes
missing module named _ctypes.Array - imported by _ctypes, ctypes
missing module named _ctypes.Union - imported by _ctypes, ctypes

None 其中以任何方式引用 Tix - 至少我发现了这一点。从我的搜索中我也知道 Tix 有点旧,但它是程序使用的,我不想更改它,因为作者最初是这样做的。他还设法为该程序生成了一个 .exe 文件,所以这不仅意味着可以这样做,而且我在这里可能做错了什么。

提前致谢。

这是一个通用的setup.py,我用Py2EXE

from distutils.core import setup
import os
import shutil
import py2exe

data_files = []
setup(
    name='ApplicationName',
    console=['Application.py'], # 'windows' means it's a GUI, 'console' It's a console program, 'service' a Windows' service, 'com_server' is for a COM server
    # You can add more and py2exe will compile them separately.
    options={ # This is the list of options each module has, for example py2exe, but for example, PyQt or django could also contain specific options
        'py2exe': {
            'packages': [],
            'dist_dir': 'dist', # The output folder
            'compressed': True, # If you want the program to be compressed to be as small as possible
            'includes': ['tix', 'os', 'logging', 'yaml', 'sqlalchemy', 'pymysql'], # All the modules you need to be included, This is where you put the package that is failing to be founhd. so if you import something inside main.py which also imports something, it might break.
        }
    },

    data_files=data_files # Finally, pass any data files

)

好的,我似乎找到了答案。将我的 python 目录中的文件与生成的文件进行比较后,我发现问题出在 py2exe 出于某种原因没有从 Tix 复制文件。

之后,我决定再次 Google 并再次找到 this 页面,并注意到我的 Tix 版本与示例中的版本不同,只是更改了脚本以匹配我的版本,让它完美运行。

这是脚本:

import glob
import os
import sys
from distutils.core import setup
import py2exe

def files(folder):
    for path in glob.glob(folder+'/*'):
        if os.path.isfile(path):
            yield path

data_files=[
            ('.', glob.glob(sys.prefix+'/DLLs/tix84*.dll')),
            ('tcl/tix8.4.3', files(sys.prefix+'/tcl/tix8.4.3/')),
            ('tcl/tix8.4.3/bitmaps', files(sys.prefix+'/tcl/tix8.4.3/bitmaps/')),
            ('tcl/tix8.4.3/pref', files(sys.prefix+'/tcl/tix8.4.3/pref/')),
           ]

setup(
      script_args=['py2exe'],
      windows=['pikasav.py'],
      data_files=data_files,
     )

如果您以后碰巧遇到这个问题并且有不同的 Tix 版本,请记住在需要时进行更改。现在我需要想出一种方法来尽可能减少文件数量,但那是完全不同的故事。