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
相关产品推荐
相关产品推荐

