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

Python程序未重启时再次调用函数,条形码图片无法替换问题

问题分析与解决方案

问题场景

以下是生成EAN8条形码的Python代码:

def Ticket_Register_Car(self):
        if(self.isTicketControl):
            numBarCode = str(self.registro[0]).zfill(7)
            print("Num:", numBarCode)
            
            if not os.path.exists('settings/ticketBarcode.png'):
                print('Se supone que no existe')
                # Selecciona el tipo de código de barras que deseas generar, en este caso 'ean8'
                hr = get_barcode_class('ean8')
                # Genera el código de barras
                barcode = hr(numBarCode, writer=ImageWriter())
                # Guarda el código de barras en un archivo
                barcode.save('settings/ticketBarcode')
            else:
                absPath = os.path.abspath('settings/ticketBarcode.png')
                absPath = absPath.replace('.png', '')
                print("Ruta sin el png: " + absPath)
                hr = get_barcode_class('ean8')
                barcode = hr(numBarCode, writer=ImageWriter())
                barcode.save(absPath)
                print('Se supone que se borró')

            self.obj.Imprimir_Ticket_Cliente()

程序首次调用该函数时,能正常替换已有图片并完成打印;但不重启程序再次调用时,图片无法被替换,导致打印失败。尝试过绝对路径、先删后生成等方法均无效。

核心原因

最可能的问题是文件句柄被锁定:C#打印函数Imprimir_Ticket_Cliente加载图片后,未正确释放文件资源,导致后续Python无法修改/覆盖该文件。其次是图片加载缓存或Python侧文件操作未释放资源。

解决方案

1. 修复C#侧的资源释放

在C#的打印函数中,确保图片资源被正确释放:

  • 使用using语句包裹Image对象,自动释放资源:
using (Image barcodeImage = Image.FromFile("settings/ticketBarcode.png"))
{
    // 执行打印逻辑
}
  • 若手动创建Image对象,打印完成后必须调用barcodeImage.Dispose()释放句柄。

2. Python侧强制清理与生成

在生成新图片前,先确保旧文件被删除(需处理文件锁定的异常):
修改代码的else分支:

else:
    absPath = os.path.abspath('settings/ticketBarcode.png')
    absPath_no_ext = absPath.replace('.png', '')
    # 尝试删除旧文件,处理可能的锁定异常
    try:
        if os.path.exists(absPath):
            os.remove(absPath)
    except PermissionError:
        # 若文件被锁定,临时重命名旧文件
        temp_name = f"settings/ticketBarcode_{int(time.time())}.png"
        os.rename(absPath, temp_name)
    # 重新生成条形码
    hr = get_barcode_class('ean8')
    barcode = hr(numBarCode, writer=ImageWriter())
    barcode.save(absPath_no_ext)

3. 规避文件锁定:使用动态文件名

每次生成不同的条形码文件名,避免覆盖旧文件,打印完成后清理历史文件:

import time
import os

def Ticket_Register_Car(self):
    if(self.isTicketControl):
        numBarCode = str(self.registro[0]).zfill(7)
        # 生成带时间戳的唯一文件名
        timestamp = int(time.time())
        barcode_filename = f'settings/ticketBarcode_{timestamp}'
        # 生成条形码
        hr = get_barcode_class('ean8')
        barcode = hr(numBarCode, writer=ImageWriter())
        barcode.save(barcode_filename)
        # 传递新文件名给C#打印函数
        self.obj.Imprimir_Ticket_Cliente(barcode_filename + '.png')
        # 清理旧的条形码文件
        for f in os.listdir('settings'):
            if f.startswith('ticketBarcode_') and f != f'ticketBarcode_{timestamp}.png':
                try:
                    os.remove(os.path.join('settings', f))
                except:
                    pass

同时修改C#打印函数,接收动态文件名参数,打印后按上述方式释放资源。

4. 禁用图片缓存

若使用的GUI框架或打印组件有图片缓存,需禁用缓存或强制刷新:

  • 在C#中加载图片时,使用Image.FromFile(path, true)(第二个参数设为true,不缓存文件):
using (Image barcodeImage = Image.FromFile(path, true))
{
    // 打印逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:35:06