如题,自己写了个小程序,有两个源文件,用到了 tkinter 库,怎么打包成 exe 文件。用 pyinstaller 打包成一个文件,但是执行有问题:点击以下 button ,就会重复新建一个窗口程序。该怎么办?
系统是 win10 64bit , python 是 2.7.10 。
1
fullpowers 2015-10-26 01:42:37 +08:00 via Android
试试 py2exe
|
2
fullpowers 2015-10-26 01:46:58 +08:00 via Android
对了, py2exe 打包非界面程序还是挺给力的。但我用 py2exe 打包带 tkinter 库的单一 exe 不能执行,非单一的就能,求解。
|
3
g00001 2015-10-26 02:03:25 +08:00
唉, python 生成 exe 这种简单的事真是让人头痛,没有 aardio 方便。
aardio 里可以 py.exec( python 代码 ) 可以用来捆绑 python 生成独立 EXE ,不过 python 的确是,引用到 pyd 的生成独立 EXE 就容易出问题。 |
4
owwlo 2015-10-26 07:46:33 +08:00
我也在用 pyinstaller 但是 UI 部分用的是 PyQt5+QtQuick 到目前为止都还不错,能详细描述下你的问题吗?
|
5
oska874 OP |
7
iwj 2015-10-26 09:11:54 +08:00
py2exe 没用过,不过,另外一个比这个更好用,而且生成的文件少。
1 )在终端下安装 pip install pyinstaller 注意,后面有 er 2 )用 cd 命令转到你的项目目录,如果要对 smart.py 进行打包,那么使用命令 pyinstaller -F smart.py -F 参数是表示生成单独的一个 exe 文件,你可以加和不加两种都试一下 随便那么一写就写复杂了,于是又提炼了一个简洁的版本放在最前面,以下是详细的: 推荐你用 PyInstaller3.0 ,我自己就在用,方便快捷。 1 )官网是 http://www.pyinstaller.org/ 英文阅读水平好的话可以进去看看 2 )在终端下安装 pip install pyinstaller 注意,后面有 er 如果没加 er 是另外一个包。安装这个包有个先决条件,不过使用 pip 命令如果你缺那个先行条件的包它会自动完成的,具体可以看对应的文档 http://pythonhosted.org/PyInstaller/#id11 这一步,我本机上实际用 pip 安装时加了 sudo 来装的,不加就无法正常安装。 3 )用 cd 命令转到你的项目目录,如果要对 smart.py 进行打包,那么使用命令: pyinstaller -F smart.py 这里的 -F 参数是表示生成单独的一个 exe 文件 这一步对应的文档是 http://pythonhosted.org/PyInstaller/#using-pyinstaller |
8
iwj 2015-10-26 09:18:55 +08:00
😓抱歉,看了你的标题,没看到你的描述。如果是像你描述的那样,建议检查代码。
|
10
oska874 OP |
11
jamiesun 2015-10-26 10:05:19 +08:00 1
|
12
fangdingjun 2015-10-26 10:07:03 +08:00
修改你的 spec 文件或者使用命令行参数,添加 console=False
exe = EXE(pyz, ... console=False, ... ) |
13
aver4vex 2015-10-26 11:41:35 +08:00
cxfreeze
|
14
owwlo 2015-10-26 14:39:57 +08:00 via iPhone
原因是你用了 process … python 库在处理你的 process 的时候 fork 了一个父进程(这样才能在另一个进程里运行出自一个文件的代码),当你把程序打包成一个文件的时候这个父进程就是你所有的代码外加 python 运行环境也就导致了你启动 server 的时候系统会再创建一个实例的现象。
解决方法 1.用 thread (不知道你是否必须使用 process ?) 2.可以再创建一个 python 脚本专门用来启动 server 进程,将这个脚本作为资源文件加入 pyinstaller ,这样当程序运行的时候这个脚本会被解压到临时目录… |
15
owwlo 2015-10-26 14:45:18 +08:00
然后在主程序里通过命令行调用启动这个脚本…但是我还没有想到好的来杀死这个脚本启动的进程方法
|
16
leavic 2015-10-26 17:21:37 +08:00
我 evernote 中记录的一个情况,是 py2exe 会默认少打包一个 dll 文件,包进去就可以了,不一定适用你的情况。
================================================== Thanks to this link, you have to edit site-packages/py2exe/build_exe.py and add "tcl85.dll" and "tk85.dll" to the dlls_in_exedir list. This will get it to run, although you'll still have the tcl folders, and those two dlls will be there along-side the exe. But it's way better than bundle_files=3. self.dlls_in_exedir = [python_dll, "w9xpopen%s.exe" % (is_debug_build and "_d" or ""), "msvcr71%s.dll" % (is_debug_build and "d" or ""), "tcl85.dll", "tk85.dll"] |
18
owwlo 2015-10-27 01:19:48 +08:00
@oska874 pyqt5 最新的 windows 预编译版本是基于 python3.4 的,我用的环境: Python3.4.3 32bit* + pyinstaller3.0 + PyQt5.5
*使用 3.4.3 是因为 PyQt5.5 的 pre-built 发行包基于 Python3.4 ,而 32bit 是由于我在代码中用了 bcrypt , bcrypt 安装时需要 msvc10 编译而 express 版的 msvc10 只包含 x86 编译器(也建议安装 32bit 的 python 因为有些库真的需要自己编译)。 还有关于你上面那个问题,如果继续使用 tkinter 的话只要把所有的 mp.Process 改成 threading.Thread 并 import threading 就可以了 |
19
Drahcir 2015-10-27 05:09:52 +08:00
|
20
geeklian 2015-10-27 23:25:45 +08:00
说说我用在“生产”环境的歪门邪道吧。
这里的生产环境,是我所在银行的上千台柜台电脑。 简而言之:用一个绿色的 python 去执行 py 文件就行了。 实现这个方法很简单: 1. 你需要一个 Anaconda/ Anaconda3 / WinPython ,三者其一,创建一个绿色的 Windows Python 环境,所需的包健全。 你可以在这两个网址下载他们: https://www.continuum.io/downloads https://winpython.github.io/ 2. 将你的程序放置成 这个样子: root -app --main.py -runtime --python.exe --..... 然后修改 phuslu 大神的一个启动器,到你想要的形态,地址 https://github.com/phuslu/taskbar ,关闭这个启动器会帮你杀死子进程。也可以重启子进程.... 其实稍微会点.net , vb , vc 都能写出一个简单的启动器。 缺点: 目前看就是体积大,这个企业内网无视了。 代码没法编译,这个其实 py2exe , cxfreeze 也很容易反编译,企业内部也无视了。 优点: 目前几乎没有 py2exe , cxfreeze , pyinstaller 这些的一切 bug 。中文路径没问题,中文文件名也没问题, QT5 无问题....反正一直使用还算良好。 |
21
oska874 OP @owwlo 果然,换成 threading 就正常了,不过有个问题,怎么杀死 threading ?、
@geeklian 没看懂你的内容。 我这么做的目的就是避免在第三方电脑上安装 python ,即使绿色的也要避免。 @fangdingjun 我试了把 console 改成 false ,但是启动的时候还是会弹出来一个 cmd 窗口,怎么去掉? |
22
owwlo 2015-10-28 00:26:50 +08:00
@oska874 python 并不提供 api 来杀死 thread ,因为 thread 是程序 process 的一部分,杀死可能会导致进程出现严重的错误。需要在代码里声明如何让线程退出。根据你的情况你在 start_transd 里面分别使用了 TftpServer 、 FTPHandler 和 HTTPServer ,需要针对每种 server 定义“停止”的方法。用 TftpServer 举例, http://tftpy.sourceforge.net/sphinx/, TftpServer 有 stop 方法,可以在 listen 的时候保存 TftpServer 的实例并在点击 stop 按钮的时候触发“ TftpServer 实例”.stop()
|