Программа на python не работает после упаковки с помощью pyinstaller

#python #pandas #tkinter #plotly #openpyxl

#python #pandas #tkinter #сюжет #openpyxl

Вопрос:

Моя программа (.py) отлично работает на платформе vscode. Однако, после упаковки в exe-файл с помощью pyinstaller, похоже, это не работает. Сообщение об ошибке «Ошибка ModuleNotFoundError: нет модуля с именем plotly.validators.scatter» Пользовательский интерфейс
Сообщение об ошибке И вот мой код «Пузырьковая диаграмма»:

 # 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()

  

И вот пример файла данных (.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
  

Что я должен сделать, чтобы решить проблему? Спасибо

Комментарии:

1. Небольшой прогресс. Я добавил import plotly.validators.scatter.marker import plotly.validators.layout.font import plotly.validators.layout.margin import plotly.validators.layout.xaxis import plotly.validators.layout.xaxis.title , теперь система подсказывает FileNotFoundError:[Ошибка 2] Нет такого файла или каталога: ‘C:user…dist\bubbleplotlypackage_data\templates\plotly.json ‘

Ответ №1:

Итак, вы все еще боретесь с этим?

Вам нужно будет обновить раздел «Данные» и «скрытые порты» вашего файла спецификации, чтобы убедиться, что библиотеки импортированы. Я показал вам свою ниже (она работает просто отлично). Вам нужно изменить ее, чтобы включить openpyxl, tkinter и 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)
  

На самом деле я получил ту же ошибку, что и вы, в отношении plotly.json, поэтому я знаю, что вышеупомянутое решение работает. 🙂

Также важно, чтобы при экспорте статического изображения вы включали Kaleido или Orcas в файл спецификации. Я использую Kaleido, поэтому вы можете увидеть это в моей настройке файла спецификации.

Затем запустите PyInstaller через: pyinstaller main.spec —clean

Где main.spec — это ваш файл спецификации (измените имя).

РЕДАКТИРОВАТЬ: Чтобы упростить задачу, вот весь мой файл спецификации:

 # -*- 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')
  

Комментарии:

1. Могу ли я проверить, почему ‘plotly’ отображается как в данных, так и в скрытом импорте, в то время как остальные отображаются только в любом из них?