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

Python多线程打印内容串行问题及并发打印解决方案需求

多线程打印内容换行异常的解决方案

问题场景

你用Python threading模块实现了多线程打印功能,支持创建任意数量线程,但运行时出现打印消息被拼接在同一行的异常情况。

原代码

import threading
import time
import random


class Useless:
    def __init__(self, numb):
        self.numb = numb

    def printing(self):
        time.sleep(random.uniform(0.05, 0.09))
        print(f'number {self.numb} is being printed God knows what for...')

    def main_loop(self):
        for _ in range(5):
            self.printing()


obj_1 = Useless(1)
obj_2 = Useless(2)

proc_1 = threading.Thread(target=obj_1.main_loop, args=())
proc_2 = threading.Thread(target=obj_2.main_loop, args=())

proc_1.start()
proc_2.start()

异常输出示例

number 2 is being printed God knows what for...number 1 is being printed God knows what for...

number 1 is being printed God knows what for...
number 2 is being printed God knows what for...
number 1 is being printed God knows what for...
number 2 is being printed God knows what for...
number 1 is being printed God knows what for...
number 2 is being printed God knows what for...
number 1 is being printed God knows what for...
number 2 is being printed God knows what for...

Process finished with exit code 0

需求:保持线程并发执行的前提下,实现打印消息各行独立。


解决方案

核心原因

Python的print操作不是原子性的,多个线程同时执行print时,可能会打断彼此的输出流程,导致部分内容拼接在同一行。

方法一:线程锁(最直接高效)

给打印操作加线程锁,确保同一时间只有一个线程能执行打印,保证输出的原子性。修改后的代码支持创建任意数量线程:

import threading
import time
import random

# 全局打印锁
print_lock = threading.Lock()

class Useless:
    def __init__(self, numb):
        self.numb = numb

    def printing(self):
        time.sleep(random.uniform(0.05, 0.09))
        # 使用with自动获取/释放锁,避免遗漏释放操作
        with print_lock:
            print(f'number {self.numb} is being printed God knows what for...')

    def main_loop(self):
        for _ in range(5):
            self.printing()

# 创建任意数量线程示例(这里创建3个)
threads = []
for thread_num in range(1, 4):
    obj = Useless(thread_num)
    t = threading.Thread(target=obj.main_loop)
    threads.append(t)
    t.start()

# 可选:等待所有线程执行完毕
for t in threads:
    t.join()

方法二:asyncio异步实现

如果想用异步方案,asyncio的事件循环是单线程调度,打印操作不会出现多线程竞争问题,同样能实现并发效果:

import asyncio
import random

class Useless:
    def __init__(self, numb):
        self.numb = numb

    async def printing(self):
        # 异步睡眠,不阻塞事件循环
        await asyncio.sleep(random.uniform(0.05, 0.09))
        print(f'number {self.numb} is being printed God knows what for...')

    async def main_loop(self):
        for _ in range(5):
            await self.printing()

async def main():
    # 创建任意数量异步任务
    tasks = []
    for task_num in range(1, 4):
        obj = Useless(task_num)
        tasks.append(asyncio.create_task(obj.main_loop()))
    # 等待所有任务完成
    await asyncio.gather(*tasks)

asyncio.run(main())

关于subprocess pipe的说明

subprocess用于创建独立子进程,进程间通信成本高,对于这个打印混乱的问题完全没必要使用,线程锁或asyncio都是更轻量高效的方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:20:24