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

Python PIL.Image.open设置图片文件夹路径触发bad mode错误排查

Tkinter图片画廊配置独立路径后PIL.open报错修复

问题现象

  • 基于Tkinter开发支持循环切换浏览的图片画廊程序,需指定图片存储的独立文件夹路径
  • 未配置独立存储路径时,图片文件与脚本共同存放在PyCharm项目同目录下,代码可正常运行
  • 配置目标文件夹路径后,执行image = PIL.Image.open(mpath, image_list[current], 'r')语句时抛出raise ValueError(f"bad mode {repr(mode)}")错误
  • 尝试将文件打开模式从'r'修改为'rb'后错误仍然复现,初步判断为PIL模块.open()方法传参逻辑冲突

问题复现代码

import PIL.Image
from PIL import ImageTk
import tkinter
import tkinter.messagebox

# path to image folder
mpath = "C:/Users/Me/Demo/DemoProject/Pics"

# List of images
image_list = ['2022-07-11_14-35-44.png', '2022-07-11_14-34-08.png']

current = 0

# Cycle through Image List
def move(delta):
    global current, image_list, mpath
    if not (0 <= current + delta < len(image_list)):
        tkinter.messagebox.showinfo('End', 'No more image.')
        return
    current += delta
    image = PIL.Image.open(mpath, image_list[current], 'r')
    photo = ImageTk.PhotoImage(image)
    fileName = image_list[current]
    print(fileName)

    # Get values from image
    def getvalues():
        img = fileName
        Dimage = PIL.Image.open(mpath, img, 'r')

        data = ''
        imgdata = iter(Dimage.getdata())

        while (True):
            pixels = [value for value in imgdata.__next__()[:3] +
                      imgdata.__next__()[:3] +
                      imgdata.__next__()[:3]]

            # string of binary data
            binstr = ''

            for i in pixels[:8]:
                if (i % 2 == 0):
                    binstr += '0'
               else:
                    binstr += '1'

            data += chr(int(binstr, 2))
            if (pixels[-1] % 2 != 0):
                return data
    print(getvalues())

    label['text'] = (str("Decoded Pic : ")+ getvalues())
    label['image'] = photo
    label.photo = photo

mRoot = tkinter.Tk()

label = tkinter.Label(mRoot, compound=tkinter.TOP)
label.pack()

frame = tkinter.Frame(mRoot)
frame.pack()

tkinter.Button(frame, text='Previous picture', command=lambda: 
move(-1)).pack(side=tkinter.LEFT)
tkinter.Button(frame, text='Next picture', command=lambda: move(+1)).pack(side=tkinter.LEFT)
tkinter.Button(frame, text='Quit', command=mRoot.quit).pack(side=tkinter.LEFT)

move(0)

mRoot.mainloop()

错误根因

  1. PIL.open传参位置错误:PIL.Image.open()的语法为Image.open(fp, mode='r', formats=None),第一个位置参数fp接收完整文件路径或文件对象,第二个位置参数mode仅支持'r'这一个合法值(代表只读模式,不接受'rb'类的普通文件打开模式)。代码中将文件夹路径、文件名、模式值拆分为三个独立参数传入,PIL会把第二个位置传入的文件名字符串识别为mode参数值,自然抛出「非法mode」的错误。
  2. 路径未做拼接:配置独立文件夹路径后,没有将文件夹路径和文件名拼接为完整的文件访问路径,直接拆分传参不符合方法的参数定义。之前同目录运行正常是因为直接传入了同目录下的文件名作为fp参数,没有出现参数错位。
  3. 代码存在隐藏语法错误:getvalues()函数内的else块缩进与对应的if语句不对齐,修正传参问题后也会触发缩进报错。

修复步骤

  1. 导入os模块做跨平台路径拼接,避免手动拼接路径出现分隔符兼容问题
  2. 所有调用PIL.Image.open()的位置,提前用os.path.join(文件夹路径, 文件名)拼接得到完整的文件路径,作为唯一的位置参数传入,不需要手动传'r'/'rb'模式值(方法默认即为只读模式)
  3. 修正else块的缩进,使其与上层if语句对齐

修复后关键代码示例

# 开头新增导入os模块
import os

# ...省略其他原有代码...

# 第一处open调用修改
current += delta
full_path = os.path.join(mpath, image_list[current])
image = PIL.Image.open(full_path)
photo = ImageTk.PhotoImage(image)

# ...省略中间代码...

    def getvalues():
        img = fileName
        # 第二处open调用修改
        full_path = os.path.join(mpath, img)
        Dimage = PIL.Image.open(full_path)

        data = ''
        imgdata = iter(Dimage.getdata())

        while (True):
            pixels = [value for value in imgdata.__next__()[:3] +
                      imgdata.__next__()[:3] +
                      imgdata.__next__()[:3]]

            binstr = ''
            # 修正缩进错误
            for i in pixels[:8]:
                if (i % 2 == 0):
                    binstr += '0'
                else:
                    binstr += '1'

            data += chr(int(binstr, 2))
            if (pixels[-1] % 2 != 0):
                return data

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:54:36