在MacOS X上使用基本的PyInstaller

2 投票
4 回答
2015 浏览
提问于 2025-04-17 17:05

我正在尝试让 pyinstaller 和我的一个 Python 脚本一起工作,但总是失败。所以我试了一个非常简单的脚本:

#!/usr/bin/env python
from matplotlib.pyplot import *
from numpy import *
x=linspace(0,2*pi,200)
plot(x,sin(x))
show()

但是这也失败了,出现了下面的错误信息。我使用的是最新的 Mountain Lion 系统,并且使用的是 Enthought Python,如果这有影响的话。我在 pyinstaller 目录下用 python pyinstaller.py --onefile ../testpyinst.py 来调用它,完整的输出信息在这里:

23 INFO: wrote xxxxxxxxxxxxxx/pyinstaller-2.0/testpyinst/testpyinst.spec
54 INFO: UPX is not available.
1263 INFO: checking Analysis
1337 INFO: checking PYZ
1350 INFO: checking PKG
1350 INFO: building because out00-PKG.toc missing or bad
1350 INFO: building PKG out00-PKG.pkg
Traceback (most recent call last):
  File "pyinstaller.py", line 91, in <module>
    main()
  File "pyinstaller.py", line 86, in main
    run_build(opts, spec_file)
  File "pyinstaller.py", line 50, in run_build
    PyInstaller.build.main(spec_file, **opts.__dict__)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 1625, in main
    build(specfile, buildpath)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 1582, in build
    execfile(spec)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/testpyinst/testpyinst.spec", line 16, in <module>
    console=True )
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 987, in __init__
    crypt=self.crypt)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 880, in __init__
    self.__postinit__()
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 315, in __postinit__
    self.assemble()
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/build.py", line 933, in assemble
    archive.build(self.name, mytoc)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/loader/archive.py", line 202, in build
    self.save_toc(tocpos)
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/loader/carchive.py", line 250, in save_toc
    tocstr = self.toc.tobinary()
  File "xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/loader/carchive.py", line 79, in tobinary
    nmlen+entrylen, dpos, dlen, ulen, flag, typcd, nm+pad))
struct.error: argument for 's' must be a string

4 个回答

0

我的问题和hxu的评论里说的一样;我把

rslt.append(struct.pack(self.ENTRYSTRUCT + repr(nmlen) + 's', nmlen + entrylen, dpos, dlen, ulen, flag, typcd, nm + pad))

改成了

rslt.append(struct.pack(self.ENTRYSTRUCT + repr(nmlen) + 's', nmlen + entrylen, dpos, dlen, ulen, flag, typcd, nm.encode('utf8') + pad))

这样就解决了,因为type(nm)是'unicode'类型,而type(pad)是字符串(str)类型。

1

我做的事情是打开这个文件 xxxxxxxxxxxxxx/pyinstaller-2.0/PyInstaller/loader/carchive.py,然后在第79行后面加了几个 print()。我发现 nm+pad 这个组合没有被识别为字符串。这有点奇怪。我使用的是 Windows 7,print() 显示 nm=kernel32pad = ''

现在说说我的临时解决办法:

rslt.append(struct.pack(self.ENTRYSTRUCT + repr(nmlen) + 's', nmlen + entrylen, dpos, dlen, ulen, flag, typcd, nm + pad))

----改成----->

try:
    rslt.append(struct.pack(self.ENTRYSTRUCT + repr(nmlen) + 's', nmlen + entrylen, dpos, dlen, ulen, flag, typcd, nm + pad))
except:
    ss = str(nm + pad)
    rslt.append(struct.pack(self.ENTRYSTRUCT + repr(nmlen) + 's', nmlen + entrylen, dpos, dlen, ulen, flag, typcd, ss))

不确定这是否是个稳妥的解决办法,但在我这里是有效的。我相信你可以用类似的方法来解决你的问题。顺便说一下,我使用的是 pyinstaller2.1 和 python2.7.6。命令是 pyinstaller -F MyApp.py --hidden-import=scipy.special._ufuncs_cxx

1

你有没有成功用 pyinstaller 做过什么项目?我建议你先写一些简单的代码,不要用外部库,

print "Hello World!"

或者

f = open('test.txt','w')
f.write("Hello World!")
f.close()

试着导入一个标准库模块,比如 math

import math
x = 10.0
y = math.sqrt(x)
print "square_root({}) = {}".format(x,y)

接下来,试着用 numpy 写个简单的代码,只打印出 sin(x),而不是尝试画图。

from numpy import *
x = linspace(0,2*pi,20)
print sin(x)

如果这样能成功,也许你可以试着用 savefig 来保存图像,而不是用 show 来显示它,看看错误是不是和显示图像有关。

from matplotlib.pyplot import *
from numpy import *
x=linspace(0,2*pi,200)
plot(x,sin(x))
savefig("/tmp/testfig.png")

如果这样还是不行,可能是你的 matplotlib 后端有问题。可以试试用一个更简单或更标准的后端:

import matplotlib
matplotlib.use("Agg")
from matplotlib.pyplot import *
from numpy import *
x=linspace(0,2*pi,200)
plot(x,sin(x))
savefig("/tmp/testfig.png")

撰写回答