项目中用到pyinstaller将python打成.exe可执行文件:
结果发现如下问题:
由于需要获取命令执行的状态值及返回信息,因此放弃了os.system,os.popen等,commands.getstatusoutput在windows平台也不能使用,因此选择subprocess模块。 os.system还有个坑,当cmd有多个引号时,会解析cmd失败。
1.subprocess.Popen调用报异常:
当使用pyinstaller打成.exe文件安装后
使用p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
报WindowsError:[Error 6]异常
单独使用subprocess.check_output(cmd)同样报此异常。
奇怪的是,直接用源码测试执行时系统完全没有任何问题。
后来才发现,当使用pyinstaller打包时,Popen应该如下初始化:
p = subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
msg = ''
for line in p.stdout.readlines():
msg += line
status = p.wait()
这样就可以轻松获取指令执行返回的状态值和信息了。
2.Multiprocessing
系统在linux下多进程正常执行,但用pyinstaller打包后在windows下,pool.apply_async(...)多进程启动没有任何反应。在网上找了很久发现:
代码中直接使用标准库中的multiprocessing.Process和multiprocessing.Pool,在打包成可执行程序后会创建进程失败。对于pyinstaller的one-directory模式,只要再程序的最开始调用multiprocessing. freeze_support()就可以了,但对于one-file模式,还需要使用下面修改后的Process和Pool。
import multiprocessing.forking
import multiprocessing.pool
import os
import sys
class _Popen(multiprocessing.forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
os.putenv('_MEIPASS2', sys._MEIPASS + os.sep)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
class Process(multiprocessing.Process):
_Popen = _Popen
class Pool(multiprocessing.pool):
Process = Process
3.此外,pyinstaller只支持ascii,打包后可执行文件路径不能有中文。
参考文章:
https://stackoverflow.com/questions/24944558/pyinstaller-built-windows-exe-fails-with-multiprocessing
https://www.aichengxu.com/view/29937
转载自:https://blog.sina.com.cn/s/blog_b1e0a3740102vpeb.html