You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.10用PyInstaller/auto-py-to-exe打包报IndexError: tuple index out of range

问题描述

我尝试将livrable.py脚本转换为exe可执行文件,使用auto-py-to-exe和PyInstaller打包时均出现相同报错IndexError: tuple index out of range。我在.py文件所在目录打开PowerShell执行打包操作,已确认该目录下安装了脚本调用的全部依赖包,也尝试使用PyInstaller开发版本打包,仍出现相同错误。

PowerShell端报错截图:
PowerShell报错
auto-py-to-exe端报错截图:
auto-py-to-exe报错

对应脚本代码

import numpy as np
import cv2
import statistics
import matplotlib.pyplot as plt
from skimage.morphology import binary_closing, binary_dilation, binary_erosion, binary_opening
from skimage.color import rgb2gray
import skimage.morphology as morpho
from PIL import Image
from scipy import ndimage
from skimage import data
from skimage.morphology import disk
from skimage.filters import threshold_otsu, rank
from skimage.filters import threshold_multiotsu
from skimage.util import img_as_ubyte
from numpy import array
import matplotlib
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import messagebox
from tkinter.filedialog import *
from skimage import morphology
from skimage.segmentation import watershed
from skimage.feature import peak_local_max
from skimage import filters

def comptage(n,f,i) :
    if n < 10 :
        n = "000" + str(n)
    else :
        if n >=10 :
            if n < 100 :
                n = "00" +str(n)
            else :
                n = "0" + str(n)
    folder = f
    imname = i + n
    im = Image.open(folder + '\\' + imname + "_TRANS.tif")
    imDAPI = Image.open(folder + '\\' + imname + "_DAPI.tif")
    imGFP = Image.open(folder + '\\' + imname + "_GFP.tif")
    imtrans = array(im)
    imdapi = array(imDAPI)
    imgfp = array(imGFP)

    sobel = filters.sobel(imtrans)
    sobel1 = sobel>0.05
    sobel1 = binary_dilation(sobel1)
    imtrans1 = sobel1 * imtrans
    thresh = cv2.threshold(imtrans1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    cv2.fillPoly(imtrans1, cnts, [255,255,255])
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4,4))
    mask = cv2.morphologyEx(imtrans1, cv2.MORPH_OPEN, kernel, iterations=5)

    imdapi1 = filters.sobel(imdapi)
    imdapi2 = imdapi1 >0.1
    imdapi3 = binary_opening(imdapi2)
    imdapi4 = imdapi * binary_closing(imdapi3)
    thresh1 = cv2.threshold(imdapi4, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    cnts1 = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts1 = cnts1[0] if len(cnts1) == 2 else cnts1[1]
    cv2.fillPoly(imdapi4, cnts1, [255,255,255])
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (4,4))
    imdapi4 = cv2.morphologyEx(imdapi4, cv2.MORPH_OPEN, kernel, iterations=1)
    imdapi4 = cv2.bitwise_and(imdapi4, mask)

    imgfp1 = cv2.threshold(imgfp, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    imgfp2 = cv2.bitwise_and(imgfp1, mask)
    imdapigfp = imdapi4 * imgfp2

    CoefBeads = 1.2083459023
    stdrd = 0.0059145257

    NbBeads = np.mean(mask)/CoefBeads
    NbLiveCells = np.mean(imdapi4)/stdrd
    NbDeadCells = ndimage.label(imdapigfp)[1]
    NbTotalCells = NbLiveCells +NbDeadCells

    resimage = [imname , NbBeads , NbLiveCells , NbDeadCells , NbTotalCells]

    return resimage

#f = r"C:\Users\sleve\EVerZom\EVerZom EVZ - Documents\A_R&D interne\Axe 2_Production d'EVs\2021\20211102-BioBLu10c1bis-hASC\09 11 2021 Production 20211102-BioBLu10c1bis-hASC\t4"
# Récupère le root du fichier contenant les images
gui = tk.Tk()
gui.title('fichier')
gui.geometry("300x100")
def getEntry():
    global f
    f = myEntry.get()
    gui.destroy()
myEntry = tk.Entry(gui, width=40)
myEntry.pack(pady=20)
btn = tk.Button(gui, height=1, width=30, text="Chemin d'accès au fichier", command=getEntry)
btn.pack()
gui.mainloop()

#i = "13"
# Récupère le nom de l'image en le demandant dans une fenêtre à l'utilisateur
gui = tk.Tk()
gui.title('image')
gui.geometry("300x100")
def getEntry():
    global i
    i = myEntry.get()
    gui.destroy()
myEntry = tk.Entry(gui, width=40)
myEntry.pack(pady=20)
btn = tk.Button(gui, height=1, width=20, text="Nom de l'image", command=getEntry)
btn.pack()
gui.mainloop()

#debut = 1
#Récupère le rang de la première photo
gui = tk.Tk()
gui.title('Rang de la première photo')
gui.geometry("300x100")
def getEntry():
    global debut
    debut = myEntry.get()
    gui.destroy()
myEntry = tk.Entry(gui, width=40)
myEntry.pack(pady=20)
btn = tk.Button(gui, height=1, width=20, text="Num photo début", command=getEntry)
btn.pack()
gui.mainloop()

#fin = 13
#Récupère le rang de la dernière photo
gui = tk.Tk()
gui.title('Rang de la dernière photo')
gui.geometry("300x100")
def getEntry():
    global fin
    fin = myEntry.get()
    gui.destroy()
myEntry = tk.Entry(gui, width=40)
myEntry.pack(pady=20)
btn = tk.Button(gui, height=1, width=20, text="Num photo fin", command=getEntry)
btn.pack()
gui.mainloop()

#Récupère le nom que l'utilisateur veut donner au fichier résultat
gui = tk.Tk()
gui.title('Nom à donner au fichier résultat')
gui.geometry("300x100")
def getEntry():
    global nomfichier
    nomfichier = myEntry.get()
    gui.destroy()
myEntry = tk.Entry(gui, width=40)
myEntry.pack(pady=20)
btn = tk.Button(gui, height=1, width=20, text="Nom fichier résultat", command=getEntry)
btn.pack()
gui.mainloop()

debut = int(debut)
fin = int(fin)
resultat = []

for n in range(debut , fin+1) :
    resultat.append(comptage(n,f,i))

resultat = array(resultat)
print(resultat)
np.savetxt(nomfichier + '.csv', resultat, fmt='%s')

该脚本在本地Python环境中可正常运行。

解决方案
  • 版本适配调整
    该报错绝大多数由Python和PyInstaller版本不兼容导致,优先卸载现有PyInstaller,安装适配性稳定的版本:

    pip uninstall pyinstaller -y
    pip install pyinstaller==5.13.2
    

    若你使用的是Python 3.12版本,建议降级到Python 3.9/3.10,这两个版本和常用的科学计算库、PyInstaller的兼容性最优。

  • 补充隐藏导入参数
    你用到的skimage、scipy、matplotlib等库存在大量PyInstaller无法自动识别的子依赖,打包时需要手动指定隐藏导入:
    直接用PyInstaller命令打包参考:

    pyinstaller --onefile --windowed --hidden-import="skimage" --hidden-import="skimage.filters.rank" --hidden-import="scipy" --hidden-import="cv2" --hidden-import="matplotlib.backends.backend_tkagg" --hidden-import="PIL" livrable.py
    

    用auto-py-to-exe的话,在「高级」-「隐藏导入」栏依次添加上述包名即可。

  • 修正路径拼接逻辑
    原代码中硬编码的反斜杠路径在打包后容易出现路径识别错误,建议导入os模块,用os.path.join拼接路径,示例如下:
    把folder + '\\' + imname + "_TRANS.tif"改为os.path.join(folder, f"{imname}_TRANS.tif")

按上述步骤操作即可正常打包,如果仍有报错,可根据打包日志中提示的缺失模块,补充对应的隐藏导入参数即可。

内容的提问来源于stack exchange,提问作者stanislas loiseau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:24:01