2012-02-06 89 views
10

我有一个问题,分发一个应用程序,利用pytz。我正在使用Py2Exe从我的Python源代码创建一个可执行文件。UnknownTimezoneError异常与Python应用程序编译与Py2Exe编译

对于我有这个问题的一个简单的例子,我有: pytz_test.py:

import pytz 

tz_au = pytz.timezone("Australia/Sydney") 
print tz_au 

和setup.py:

from distutils.core import setup 
import py2exe 

setup(console=['pytz_test.py'], options={"py2exe" : { 'packages': ['pytz'], } }) 

我然后运行setup.py :

python setup.py py2exe 

编译可执行文件。运行创造pytz_test.exe我得到:

我想这是因为时区信息不得到与可执行文件捆绑在一起,但我不知道如何做到这一点。

编辑: 简单的解决办法是添加区信息目录,从在Python site-packages目录的pytz模块,到library.zip

要自动做到这一点,我也跟着在项目的解决方案谷歌公交数据饲料中使用,来自: http://code.google.com/p/googletransitdatafeed/source/browse/trunk/python/setup.py

我修改setup.py现在看起来像:

from distutils.core import setup 
import glob 
import py2exe 

options = { 
    "py2exe" : { 
     "compressed": 1, 
     "optimize": 2, 
     'packages': ['pytz'], 
    } 
} 

setup(console=['pytz_test.py'], options=options) 

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() 
+0

您还需要当前版本的setuptools。特别是pkg_resources。 'import pkg_resources'一定不能失败。 – sbaechler 2012-05-01 13:41:48

+0

pkg_resources在哪里使用?或只是通过导入它? – Triztian 2012-08-30 04:45:48

回答

3

一个简单的解决方案是将zoneinfo目录中的pytz模块添加到python站点包中目录,到library.zip

要自动做到这一点,我也跟着解决方案项目谷歌公交数据饲料中使用,来自:

我修改setup.py现在看起来像:

from distutils.core import setup 
import glob 
import py2exe 

options = { 
    "py2exe" : { 
     "compressed": 1, 
     "optimize": 2, 
     'packages': ['pytz'], 
    } 
} 

setup(console=['pytz_test.py'], options=options) 

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() 

(通过提问者回答)

2

手动压缩zoneinfo(如Jason S所述)帮助buildin g在我的一台电脑上安装软件包。 但是,当我在另一台计算机上构建包时,错误又回来了! 寻找原因花了我一段时间 - 所以我最好分享一下。

建议的解决方案不适用于新的pytz版本(至少在2014.7)! 挖掘为什么显示pytz将zoneinfo文件的格式从pyc更改为某种二进制格式。对我来说,看起来像这样,他们“打破”了将pytz打包成zip的选项,因为python的内置zipimport机制不能用于加载二进制文件。 其实,这个问题应该由pytz是固定的,但现在我发现了另一个解决方案:

  • 只需直接复制整个pytz目录到您的dist目录
  • 你的程序中,添加main-的路径exectutable Python的搜索路径

实际上,这意味着你的setup.py内更换pytz-荏苒与

import pytz, os, shutil 
srcDir = os.path.dirname(pytz.__file__) 
dstDir = os.path.join('dist', 'pytz') 
shutil.copytree(srcDir, dstDir, ignore = shutil.ignore_patterns('*.py')) 

,并从“包” - 选项移动pytz为“排除”:

options = { 
    "py2exe" : { 
     "compressed": 1, 
     "optimize": 2, 
     "packages": [], 
     "excludes": ['pytz'] 
    } 
} 

在你的程序的主入口(以确保它是进口pytz之前执行),你就需要补充一下如:

import os, sys 
basePath = os.path.dirname(os.path.abspath(sys.argv[0])) 
sys.path.insert(0, basePath) 
+0

这对我有用(pytz 2014.10),但我不得不从shutil.copytree()中删除所有的忽略。 – Geotob 2015-02-14 10:35:15

+0

是的!有效!最奇怪的事情是,我pytz与py2exe工作。然后我在我的程序中修改了一些与pytz完全无关的东西,并突然停止工作,准确地给了UnkownTimeZoneError – wordsforthewise 2015-04-09 06:49:54

+0

字!那也是我的问题。因为(至少对我来说)py2exe做什么以及如何收集它的东西并不总是显而易见的,我甚至不得不将调试打印到pytz中以找出在py2exe收集阶段发生了什么问题。 :-) – Zappotek 2015-07-24 09:13:14