简体   繁体   中英

Program in python doesn't work after packaging with pyinstaller

My program(.py) runs perfectly on platform vscode. However, after packaging to .exe file with pyinstaller, it doesn't seem to work. The Error message is "ModuleNotFoundError: No module named plotly.validators.scatter" 用户界面 错误信息 And here is my code "Bubble Diagram":

# Bubble Diagram Version3.0


import tkinter as tk
import tkinter.filedialog as fd
import plotly as py
import plotly.graph_objs as go
import openpyxl
import pandas as pd
import os


class App(tk.Tk):

    def __init__(self):
        super().__init__()
        self.path1 = fd.StringVar()
        self.path2 = fd.StringVar()
        self.name_input = fd.StringVar()
        group_1 = tk.LabelFrame(self, padx=15, pady=10,
                                text="Input and Output Settings")
        group_1.pack(padx=10, pady=5)
        tk.Label(group_1, text='Step1').grid(row=0, column=0)
        tk.Button(group_1, text="Import data from", bg='green',
                  width=20, command=self.choose_file).grid(row=0, column=1)
        tk.Label(group_1, textvariable=self.path1, width=40, bg='grey', fg='white').grid(row=0, column=2, pady=5)
        tk.Label(group_1, text='Step2').grid(row=1, column=0)
        tk.Button(group_1, text="Set output path", bg='orange',
                  width=20, command=self.choose_directory).grid(row=1, column=1)
        tk.Label(group_1, textvariable=self.path2, width=40, bg='grey', fg='white').grid(row=1, column=2, pady=5)
        tk.Label(group_1, text='Step3').grid(row=2, column=0)
        tk.Label(group_1, text='Input name WITHOUT suffix', bg='SteelBlue', width=20).grid(row=2, column=1)
        tk.Entry(group_1, textvariable=self.name_input, bg='grey', width=40).grid(row=2, column=2)

        group_2 = tk.LabelFrame(self, padx=15, pady=10, text="Implementation")
        group_2.pack(padx=10, pady=5)
        tk.Label(group_2, text='Step4').grid(row=0, column=0)
        tk.Button(group_2, text="Start to plot", bg='red',
                  width=10, command=self.start).grid(row=0, column=1)

    def choose_file(self):
        filetypes = (("Excel files", "*.xlsx"),
                     )
        self.filename = fd.askopenfilename(title="Open file",
                                           initialdir="/", filetypes=filetypes)
        self.path1.set(self.filename)

    def choose_directory(self):
        self.directory = fd.askdirectory(title="Open directory",
                                         initialdir="/")
        self.path2.set(self.directory)

    def start(self):
        self.draw(self.filename, self.directory)

    def draw(self, input_file, output_dir):
        self.input_file = input_file
        self.output_dir = output_dir
        wb = openpyxl.load_workbook(self.input_file)
        sheet = wb['Sheet1']
        row_max = sheet.max_row
        col_max = sheet.max_column
        first_row_list = []
        first_col_list = []
        for col_n in range(2, col_max + 1):
            first_row_list.append(sheet.cell(row=1, column=col_n).value)
        for row_n in range(2, row_max + 1):
            first_col_list.append(sheet.cell(row=row_n, column=1).value)

        data_all = pd.read_excel(self.input_file)
        data_selected = data_all.loc[:, first_row_list]

        df = pd.DataFrame(data_selected)
        df.index = first_col_list
        colors = ['rgb(150,204,90)', 'rgb(255, 130, 71)', 'rgb(255, 193, 37)', 'rgb(180,240,190)', 'rgb(255, 10, 1)',
                  'rgb(25, 190, 30)', 'rgb(100, 100, 100)', 'rgb(45,24,200)', 'rgb(33, 58, 108)', 'rgb(35, 208, 232)']

        data = [go.Scatter(
            x=df.columns,
            y=[country] * len(df.columns),
            mode='markers+text',
            marker=dict(
                color=colors[num],
                size=df.loc[country],
                showscale=False,
            ),
            text=list(map(str, df.loc[country])),
            textposition='middle center',
        )
            for num, country in enumerate(reversed(df.index))
        ]

        layout = go.Layout(plot_bgcolor='rgb(10, 10, 10)',
                           paper_bgcolor='rgb(20, 55, 100)',
                           font={
                               'size': 15,
                               'family': 'sans-serif',
                               'color': 'rgb(255, 255, 255)'
                           },
                           width=1000,
                           height=800,
                           xaxis=dict(
                               title='Output of grapes per year in different countries',
                               nticks=col_max + 1,
                               type='category',
                           ),
                           showlegend=False,
                           margin=dict(l=100, r=100, t=100, b=100),
                           hovermode=False,
                           )

        fig = go.Figure(data=data, layout=layout)
        self.name = self.name_input.get() + '.html'
        py.offline.plot(fig, filename=os.path.join(self.output_dir, self.name))


if __name__ == "__main__":
    app = App()
    app.title("Bubble Diagram")
    app.mainloop()

And here is the example data file(.xlsx):

       1991  1992  1993  1994  1995  1996  1997
US       10    14    16    18    20    42    64
JAPAN   100    30    70    85    30    42    64
CN       50    22    30    65    70    66    60

What should I do to solve the problem? Thx

So are you still struggling with this?

You would need to update your spec file's "data" and "hiddenimports" section to ensure the libraries are imported across. I've shown you mine below (it works just fine). You need to modify it to include openpyxl, tkinter and pandas.

a = Analysis(['main.py'],
             pathex=['C:\\Users\\user\\PycharmProjects\\PlotlyExample'],
             binaries=[],
             datas=[('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\plotly\\', 'plotly'),
             ('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\kaleido\\', 'kaleido'),
             ('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\pptx\\', 'pptx'),],
             hiddenimports=['pandas','numpy','plotly','pptx'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

I actually got the same error as you regarding plotly.json so I know the above solution works. :)

It's also important that if you're doing static image export - that you include either Kaleido or Orcas in the spec file. I'm using Kaleido so you can see it in my spec file setup.

Then run PyInstaller via: pyinstaller main.spec --clean

Where main.spec is your spec file (change the name).

EDIT: To make things easier, here's my entire spec file:

# -*- mode: python ; coding: utf-8 -*-
# Command to compile the spec and python files
# pyinstaller main.spec --clean --onefile

block_cipher = None


a = Analysis(['main.py'],
             pathex=['C:\\Users\\user\\PycharmProjects\\PlotlyExample'],
             binaries=[],
             datas=[('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\plotly\\', 'plotly'),
             ('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\kaleido\\', 'kaleido'),
             ('C:\\Users\\user\\PycharmProjects\\PlotlyExample\\venv\\Lib\\site-packages\\pptx\\', 'pptx'),],
             hiddenimports=['pandas','numpy','plotly','pptx'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='main',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='main')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM