如何实现列表中每个元素对应打印一张票据?
票据打印重复最后一个元素问题的解决方案
核心原因
问题根源是文件写入的缓冲区未及时同步到磁盘,或者打印操作在内容真正落地前就执行了。Python文件写入默认采用缓冲机制,循环内的write操作可能只是把内容存在内存里,没立刻写到磁盘,导致打印程序读取的始终是旧内容;等循环结束后缓冲区一次性刷新,所有打印任务最终读取的都是最后一次写入的内容。
可行解决方法
方法1:强制刷新缓冲区并确保文件关闭
每次写入后立刻刷新缓冲区并关闭文件,保证内容写入磁盘后再触发打印。示例代码:
import win32api import win32print ticket_contents = ["票据A内容", "票据B内容", "票据C内容"] temp_file = "ticket_temp.txt" for content in ticket_contents: # 覆盖写入文件,使用with语句自动处理关闭 with open(temp_file, "w", encoding="utf-8") as f: f.write(content) f.flush() # 强制把内存内容刷到磁盘 # 执行打印 win32api.ShellExecute( 0, "print", temp_file, f'/d:"{win32print.GetDefaultPrinter()}"', ".", 0 )
方法2:使用临时文件避免覆盖冲突
给每个票据生成独立的临时文件,打印完成后删除,彻底避免文件覆盖的竞态问题:
import win32api import win32print import tempfile import os import time ticket_contents = ["票据A内容", "票据B内容", "票据C内容"] for content in ticket_contents: # 创建不自动删除的临时文件 with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as f: f.write(content) temp_path = f.name # 执行打印 win32api.ShellExecute( 0, "print", temp_path, f'/d:"{win32print.GetDefaultPrinter()}"', ".", 0 ) # 短暂延迟确保打印进程读取完文件再删除 time.sleep(0.5) os.unlink(temp_path)
方法3:改用同步打印方式
ShellExecute是异步执行的,可能打印还没读取文件,下一次循环就覆盖了内容。可以使用win32print的同步打印接口,确保打印完成后再进行下一次写入:
import win32print import win32api ticket_contents = ["票据A内容", "票据B内容", "票据C内容"] printer_name = win32print.GetDefaultPrinter() h_printer = win32print.OpenPrinter(printer_name) try: for content in ticket_contents: # 创建打印作业 job_info = win32print.StartDocPrinter(h_printer, 1, ("Ticket", None, "TEXT")) win32print.StartPagePrinter(h_printer) # 写入打印内容 win32print.WritePrinter(h_printer, content.encode("utf-8")) win32print.EndPagePrinter(h_printer) win32print.EndDocPrinter(h_printer) finally: win32print.ClosePrinter(h_printer)
之前尝试无效的原因
- 把
close()移到循环外:整个循环结束才关闭文件,所有写入都积压在缓冲区,打印时读取的始终是未更新的文件内容,直到最后一次写入才刷新到磁盘。 - 删除
close()语句:Python会在文件对象被垃圾回收时自动关闭,但循环内的文件对象可能未被及时回收,缓冲区未刷新,导致打印读取的还是旧内容。
内容的提问来源于stack exchange,提问作者MR.GOBBO
相关产品推荐
相关产品推荐

