使用 Py2Exe 编译的 Python 应用程序引发 UnknownTimezoneError 异常 [英] UnknownTimezoneError Exception Raised with Python Application Compiled with Py2Exe

查看:52
本文介绍了使用 Py2Exe 编译的 Python 应用程序引发 UnknownTimezoneError 异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在分发使用 pytz 的应用程序时遇到问题.我正在使用 Py2Exe 从我的 Python 源代码创建一个可执行文件.

I'm having a problem distributing an application that utilizes pytz. I'm using Py2Exe to create an executable from my Python source.

对于我遇到的问题的一个简单示例,我有:pytz_test.py:

For a simple example of the problem I'm having, I have: pytz_test.py:

import pytz

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

在 setup.py 中:

and in setup.py:

from distutils.core import setup
import py2exe

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

然后我运行 setup.py:

I then run setup.py:

python setup.py py2exe

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

Which compiles the executable. Running the created pytz_test.exe I get:

Traceback (most recent call last):
  File "pytz_test.py", line 3, in <module>
    tz_au = pytz.timezone("Australia/Sydney")
  File "pytz\__init__.pyc", line 185, in timezone
pytz.exceptions.UnknownTimeZoneError: 'Australia/Sydney'

我认为这是因为时区信息没有与可执行文件捆绑在一起,但我不确定如何实现.

I assume it is because the timezone information isn't getting bundled with the executable, but I'm not sure how to make it happen.

一个简单的解决方案是将 zoneinfo 目录从 python site-packages 目录中的 pytz 模块添加到 library.zip.

A simple solution would be to add the zoneinfo directory, from the pytz module in the python site-packages directory, to the library.zip.

为了自动执行此操作,我遵循了Google Transit Data Feed 项目中使用的解决方案,来自:http://code.google.com/p/googletransitdatafeed/source/browse/trunk/python/setup.py

To do this automatically, I followed the solution in that project Google Transit Data Feed used, from: http://code.google.com/p/googletransitdatafeed/source/browse/trunk/python/setup.py

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

My modified setup.py now looks like:

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

推荐答案

手动压缩 zoneinfo(如 Jason S 所述)确实有助于在我的一台计算机上构建包.但是,当我在另一台计算机上构建包时 - 错误又回来了!找到原因花了我一段时间 - 所以我最好分享一下.

Zipping the zoneinfo manually (as described by Jason S) helped indeed for building the package on one of my computers. However, when I built the package on another computer - the error was back! Finding the reason took me a while - so I'd better share.

建议的解决方案不适用于新的 pytz 版本(至少在 2014.7 中)!挖掘为什么会发现 pytz 将 zoneinfo 文件的格式从 pyc 更改为某种二进制格式.在我看来,通过这种更改,他们破坏"了将 pytz 打包成 zip 的选项,因为 python 的内置 zipimport 机制不适用于加载二进制文件.实际上,这个问题应该由 pytz 解决 但是现在我找到了另一个解决方案:

The proposed solution doesn't work with new pytz-versions (at least with 2014.7)! Digging why this is revealed that pytz changed the format of the zoneinfo files from pyc to some binary format. To me it looks like, with this change they "broke" the option to pack pytz into a zip, since the builtin zipimport mechanism of python doesn't work for loading binary files. Actually, this problem should be fixed by pytz but for now I found another solution:

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

实际上,这意味着在您的 setup.py 中将 pytz-zipping 替换为

Practically, this means within your setup.py replace the pytz-zipping with

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 从packages"-option 移动到excludes":

and move pytz from the "packages"-option to "excludes":

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

在程序的主入口处(确保在导入 pytz 之前执行),您必须添加如下内容:

At the main entry of your program (to make sure it is executed before importing pytz), you would have to add something like:

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

这篇关于使用 Py2Exe 编译的 Python 应用程序引发 UnknownTimezoneError 异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆