之前也有使用过pyinstaller打包脚本,没有遇到什么问题,今天突然一下子遇到了好多问题,觉得有必要记录一下。
我使用的windows64的平台,python版本为3.7.2,是使用ananconda进行安装的,需要打包的脚本是使用jupyter写的,很简单的一个用来统计结果的脚本,就用到了pandas和openpyxl两个库
这个脚本是用来统计当前目录下xlsx文件中两个比较简单的数据,因为实验需求,每次打完质谱使用PD后都要做这么一个简单的统计,如果样本较多的时候统计起来就比较累。
import os
import openpyxl
import pandas as pd
os.chdir("./")
#get all xlsx files
def get_all_xlsx():
all_xlsx = [i for i in os.listdir() if ((i.endswith("xlsx")) and not (i.startswith("~$")))]
if len(all_xlsx) == 0:
print("There is no xlsx format file.")
input("Press any key to exit.")
os._exit(0)
else:
return all_xlsx
class DS:
def __init__(self,filename):
self.filename = filename
def detect_file_type(self):
wk = openpyxl.load_workbook(self.filename)
sheetnames = wk.sheetnames
if sheetnames[0] == "PeptideGroups":
return "pep"
elif sheetnames[0] == "ProteinGroups":
return "pro"
else:
return "none"
def change_to_dataframe(self):
workbook = pd.read_excel(self.filename,sheet_name=0)
return workbook
def pep_process(dataframe):
rows = len(dataframe.index)
#print(rows)
phos = dataframe.loc[:,"Modifications"].str.contains("Phospho").tolist().count(True)
#print(phos)
phos_rate = phos/rows
pros = len(set(dataframe.loc[:,"Master Protein Accessions"].values.tolist()))
return pros,phos,rows,phos_rate
def pro_process(dataframe):
rows = dataframe.shape[0]
return rows
#"{filename} is not a pep or pro file".formatmat(filename=filename)
# 读入文件
def main():
all_xlsx = get_all_xlsx()
outFile = open("DataStastic.txt","w")
for f in all_xlsx:
ds = DS(f)
fileType = ds.detect_file_type()
workbook = ds.change_to_dataframe()
if fileType == "pep":
results = pep_process(workbook)
outline = f + "\t" + str(results[0]) +"\t"+"PhosphoRatio:"+str(results[1])+"/"+str(results[2])+"="+str(results[3])+"\n"
outFile.writelines(outline)
print(outline,end="")
elif fileType == "pro":
results = pro_process(workbook)
outline = f + "\t" + str(results)+"\n"
print(outline,end="\n")
outFile.writelines(outline)
outFile.close()
print("results are in DataStastic.txt")
input("press any key to exit.")
main()
在使用pyinstaller进行打包时报错RecursionError: maximum recursion depth exceeded,意思是超出最大递归深度,python默认最大递归深度为999,这个问题可以通过下面的方式来解决
#首先正常运行pyinstaller
pyinstaller -F PD_stastic.py
在报出以上错误后,可以在当前目录下面看到一个PD_stastic.spec的文件,在该文件中加入:
import sys
sys.setrecursionlimit(10000)
修改前:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['PD_stastic.py'],
pathex=['c:/Windows/System32/downlevel', 'D:\\notebook\\Data statistics of
修改后:
# -*- mode: python ; coding: utf-8 -*-
import sys
sys.setrecursionlimit(10000)
block_cipher = None
a = Analysis(['PD_stastic.py'],
pathex=['c:/Windows/System32/downlevel', 'D:\\notebook\\Data statistics of
接下来运行:
pyinstaller -F PD_stastic.spec
刚开始的时候sys.setrecursionlimit(10000)我设置为了5000,结果依旧报错,就加大到了10000
虽然成功的进行了打包,但是打包后的程序居然有20几兆,所以运行速度奇慢,接下来就是如何解决这个问题
上网查询后大家都说是ananconda的问题,会打包很多多余的东西进去,因此接下来就准备安装一个纯净的pyton,这里的版本与ananconda’中的版本保持一致
python37 D:/py37/Scripts/pip37.exe install pandas openpyxl pyinstaller
由于原python中的pyinstaller也存在于环境变量中,所以这里使用绝对路径调用
pyton37 D:/py37/Scripts/pyinstaller.exe
结果报错了…
这里是说编码有问题,对于这种问题,网上的解决办法都是在python文件的头部加入:
#coding:utf-8
或者
#coding:gbk
等等的方法,这些方法对于我自己写的py脚本可能适用,但是对于一个exe程序我有点无存下手,但好在阴差阳错的解决了
就结果来看,依旧是和原python有冲突,这里进行修改文件名
原 | 修改为 |
---|---|
D:/py37/Scripts/pyinstaller.exe | D:/py37/Scripts/pyinstaller37.exe |
D:/py37/Scripts/pyinstaller-script.exe | D:/py37/Scripts/pyinstaller37-script.exe |
想不到居然解决了:
下面是进行打包的完整代码:
pyinstaller37 -p c:/Windows/System32/downlevel -F -i chuyin.ico PD_stastic.py
参数 | 说明 |
---|---|
-p | 指定依赖库的位置,否则会有警告某个dll文件摘不到,一般都是存在于c:/Windows/System32/downlevel |
-i | 指定图标文件的位置,可以用于生成exe文件的图标,我这里使用初音小姐姐的图片,ico格式可以使用jpg文件在线转换 |
-F | 只生成单个的exe文件,位于当前目录下的dist目录中 |
-w | 生成的exe程序采用无命令行窗口运行 |
原因就是我的脚本中使用了input函数,而input函数需要在命令行窗口出入,所以产生了冲突。。。