每日归档: 2018年9月12日

wxpython加pyinstaller加pyecharts(解决python打包exe不兼容问题)

简单介绍:wxpython和pyecharts可以搭配使用,在桌面程序中展示web形式的图表。但是在使用pyinstaller打包成exe文件后,可能会出现如下BUG:

BUG1:在用pyinstaller将wxpython程序打包成exe文件后,运行会发生TemplateNotFound: simple_chart.html的报错信息。

这时候,需要把pyechats 的在python环境里的html文件拷贝出来,目录用/pyecharts/templates/ 然后放置在pyinstall打包后的主程序文件夹目录下

BUG2.生成了HTML文件之后,没有加载JS

1.去echarts官网下载echarts.common.min.js放在resource目录下
2.修改Libsite-packagespyechartstemplates的simple_page.html和simple_chart.html 的{{ echarts_js_dependencies(chart) }} 变成<script type=”text/javascript” src=”../echarts.common.min.js”></script>,然后重新打包
(补充解释:把echarts.common.min.js 放在pyecharts生成的HTML文件的上级目录里,对应src=”../echarts.common.min.js”)
4.修改wxpython的代码,在frame里增加一个webview

self.frame = reportFrame.MyFrame(None, wx.ID_ANY, "")
self.wv = webview.WebView.New(self.frame.panel_1, size=(500, 600)) # 加了这行就能整体拖动了
name = os.path.abspath(os.getcwd() + './resource/reports/init_report.html')
self.wv.LoadURL("file:///"+name)

5.把pyecharts/template目录和resource目录一起拷贝到manage目录下(manage是因为我打包的时候用的命令是pyinstaller -D manage.py)
因为有读者不是很明白文件结构,下面附上我的resource目录和pyechart生成的结构html文件目录
resource目录


生成的html文件里的内容

jinja2不兼容pyinstaller打包exe程序的解决办法

jinja2是python下的一个根据html模板,产生html文件的库。在jinja2官方文档中,推荐使用PackageLoader的方式,产生html文件,但是这个方式却与pyinstaller冲突,所以我们需要修改成FileSystemLoader的方式来解决打包文件的问题。

不兼容pyinstall的老代码(PackageLoader产生HTML文件)
#使用PackageLoader产生html文件
def create_defect_html(defectlist, fileds, reportname=None):
    """
    create html defects report in "./reports" directory
    :param defectlist:传入问题单列表
    :param fileds:传入问题单关键字列表
    :param reportname:传入报告文件名称,若有需要可以指定生成的html报告名称;若不传,则默认为DefectList.html
    :return:无返回,在reports目录下生成html报告
    """
    mycolumnlist = col_transform(fileds)
    env = Environment(loader = PackageLoader('TAReport', 'templates'))
    template = env.get_template('DefectTemplate.html')
    if reportname:
        filestr = './reports/' + reportname + '.html'
    else:
        filestr = './reports/DefectList.html'
    with open(filestr, 'w+') as f:
        f.write(str(template.render(defectlist=defectlist, columnlist=mycolumnlist)))
使用FileSystemLoader,能够正确使用pyinstaller打包的新代码
from jinja2 import Environment, PackageLoader, FileSystemLoader
def create_defect_html(defectlist, fileds, reportname=None):
    """
    create html defects report in "./reports" directory
    :param defectlist:传入问题单列表
    :param fileds:传入问题单关键字列表
    :param reportname:传入报告文件名称,若有需要可以指定生成的html报告名称;若不传,则默认为DefectList.html
    :return:无返回,在reports目录下生成html报告
    """
    mycolumnlist = col_transform(fileds)
    template_file_name = "DefectTemplate.html"
    template_file_path = resource_path('resource/templates', template_file_name)
    template_file_directory = os.path.dirname(template_file_path)
    template_loader = FileSystemLoader(searchpath=template_file_directory)
    env = Environment(loader=template_loader)
    template = env.get_template(template_file_name)
    if reportname:
        filestr = os.path.abspath(os.getcwd() + "./resource/reports/" + reportname + '.html')
        # filestr = './resource/reports/' + reportname + '.html'
    else:
        filestr = os.path.abspath(os.getcwd() + "./resource/reports/DefectList.html")
        # filestr = './resource/reports/DefectList.html'
    html = template.render(defectlist=defectlist, columnlist=mycolumnlist)
    with open(filestr, 'w') as f:
            f.write(html)
def resource_path(relative_path, file_name):
    """ Get absolute path to resource, works for both in IDE and for PyInstaller """
    # PyInstaller creates a temp folder and stores path in sys._MEIPASS
    # In IDE, the path is os.path.join(base_path, relative_path, file_name)
    # Search in Dev path first, then MEIPASS
    base_path = os.path.abspath(".")
    dev_file_path = os.path.join(base_path, relative_path, file_name)
    if os.path.exists(dev_file_path):
        return dev_file_path
    else:
        base_path = sys._MEIPASS
        file_path = os.path.join(base_path, file_name)
        if not os.path.exists(file_path):
            msg = "nError finding resource in either {} or {}".format(dev_file_path, file_path)
            print(msg)
            return None
        return file_path

苏ICP备18047533号-2