由于py2exe打包的时候会自动根据你代码中的引用把资源给打包进来,但是凡事不是绝对的,代码中可能会有隐形的引入了其他的py文件或资源文件的时候是无法自动识别的,所以就需要手动的配置,或者做一些手动操作了,还有也可以在自己代码中先把隐形的引入用显式的引入把py文件导入比如:
# 这个是打包apscheduler确实存在的问题,后面两个是因为后面的问题而引入的
from apscheduler.triggers.cron import *from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.date import DateTrigger
最先我遇到的问题是打包后打开exe后报错:pkg_resources.DistributionNotFound: APScheduler,这个问题搜了很久都没找到解决方案,后来硬着头皮看了下源代码,发现apscheduler/__init__.py里面代码是这样的:
# These will be removed in APScheduler 4.0.
release = __import__('pkg_resources').get_distribution('APScheduler').version.split('-')[0]
version_info = tuple(int(x) if x.isdigit() else x for x in release.split('.'))
version = __version__ = '.'.join(str(x) for x in version_info[:3])
发现在打包后的发现可能是没有把APScheduler-3.3.0.dist-info资源文件打包进来导致get_distribution('APScheduler')报错了,我想这个文件好像没什么实质作用啊,然后这段代码就是为了获取apscheduler的版本号用的,所以我就把这里面的代码全部注释了,然后打包后打开exe不报这个错了,而且原来的功能也没问题,所以这应该也算是解决方法之一吧。
但这个之后有报错:pytz.exceptions.UnknownTimeZoneError: 'Asia/Shanghai',这个我也跟了下源码,发现打包的时候又缺少文件,我那个汗。。。
这个有两个方法:
- 手动复制这个zoneinfo文件到打包后的library.zip/pytz下
- 自己在setup.py里面写代码复制过来
总之把文件拷贝过来就对了,具体代码下面会上,请往下看
但是其他的资源文件,1、图片、文本类型等的非第三方库的文件 2、第三方库文件
如果是第一种情况可以在setup中这样配置下即可:
setup(windows=["main.py"],
options={"py2exe": {
'packages': ['pytz']
}},
# 静态资源文件路径配置
data_files=[("img", ["img/picon.ico"]),
("config", ["config/config.json"])])
如果是第二种情况就要麻烦点了:
# coding=utf-8
__author__ = 'carlos'
from distutils.core import setup
import py2exe
setup(windows=["main.py"],
options={"py2exe": {
'packages': ['pytz']
}},
# 静态资源文件路径配置
data_files=[("img", ["img/picon.ico"]),
("config", ["config/config.json"])])
# 打包pytz时候缺少文件zoneinfo里的所有文件,这里是手动添加回去了
import pytz
import os
import zipfile
zipfile_path = os.path.join("dist/" 'library.zip')
z = zipfile.ZipFile(zipfile_path, 'a')
zoneinfo_dir = os.path.join(os.path.dirname(pytz.__file__), 'zoneinfo')
disk_basedir = os.path.dirname(os.path.dirname(pytz.__file__))
for absdir, directories, filenames in os.walk(zoneinfo_dir):
assert absdir.startswith(disk_basedir), (absdir, disk_basedir)
zip_dir = absdir[len(disk_basedir):]
for f in filenames:
z.write(os.path.join(absdir, f), os.path.join(zip_dir, f))
z.close()
或者自己手动复制这个zoneinfo文件到打包后的library.zip/pytz下。这个是打包含有pytz库的时候会有这个问题,其他如果打包遇到了此问题可以往这条路上看看,也许就是这个问题,哈哈^^!
但是打包后还是报错:No trigger by the name "interval" was found,网上搜了下这个答案就比较多了,原因如下:
原来的代码是:
self.scheduler.add_job(self.DoCmd, item.get('trigger'), args=(item.get('cmd'), item.get('name')), **params)
修改为:
trigger_name = '%s%s' % (item.get('trigger').capitalize(), 'Trigger')
trigger = eval(trigger_name)(**params)
self.scheduler.add_job(self.DoCmd, trigger, args=(item.get('cmd'), item.get('name')))
因为用到了IntervalTrigger, CronTrigger和DateTrigger所以上面引入了,哎呀妈呀,一个接一个问题,不得不说py2exe也不能这么智能啊,总会有这么多问题,其实我也看过其他的打包方法比如pyinstaller和cx_Freeze都有这些问题,想想看应该也是的,有些非直接的引路很难查询到,可能大牛可以吧,反正至少我没这个功底能办到呵呵...
这里提示下初次用py2exe的人,也给自己提个醒以防自己忘记:
py2exe打包在不同win环境下打出来的包不是可以运用于所有的win环境的,比如我再win10中打包出来的放在某些xp下就不能运行,应该是缺少一些dll文件,如果遇到这类问题试试在xp底下打包,可能可以解决这个问题。