Python多线程写文件实例

由于最近一段时间,学了一门脚本语言-Python,原因是一、公司需要;二、只掌握Java感觉还是不够。
由于需要用python分析日志,但是日志实际还没有,格式已经定了,所以我先用python写了个多线程写文件的工具,比较简单,作为一个学习总结吧,同时还遇到了一个问题,顺便将问题和解决方法也总结一下。
需求:两个线程同时向一个文件中写固定格式的文件
实际代码:

# -*- coding: utf-8 -*-

import threading

'''
多线程生成日志工具
'''

__author = [
'"yangfei" <yangfei@ptmind.com>'
]

#该方法主要用于写入300行WARN日志
def writeWarnLog(file):
count=0;
while count<300:
try:
file.write('2012-11-28 22:51:01|zookeeper|WARN|m1|172.17.1.15\n')
count+=1
except Exception ,e:
print 'write warn log error',str(e)
break
print 'write warn log finished'

#该方法主要用于写入100行ERROR日志
def writeErrorLog(file):
count=0;
while count<100:
try:
file.write('2012-12-12 22:22:22|zookeeper|ERROR|m1|all\n')
count+=1
except Exception ,e:
print 'write error log error',str(e)
break
print 'write error log finished'

def main():
fileName='zookeeper.log'
mode='w+' #通过追加写日志文件
#创建两个线程来写文件
try:
f=open(fileName,mode)
t1=threading.Thread(target=writeWarnLog,args=(f))
t2=threading.Thread(target=writeErrorLog,args=(f))

t1.start()
t2.start()

t1.join()
t2.join()
except Exception,e:
print 'write log failed,',str(e)
finally:
f.close()
print 'write log finished'

if __name__=='__main__':
main()

这上面的代码存在Bug,直接运行的话,会出现如下错误信息:

Exception in thread Thread-2:
Traceback (most recent call last):
File "/opt/python/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/opt/python/lib/python2.7/threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
TypeError: writeErrorLog() takes exactly 1 argument (0 given)

Exception in thread Thread-1:
Traceback (most recent call last):
File "/opt/python/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/opt/python/lib/python2.7/threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
TypeError: writeWarnLog() takes exactly 1 argument (0 given)

异常是说,两个线程的执行的方法需要一个参数,而我并没有给参数,但是通过实际代码查看,明明是都给了一个参数:

t1=threading.Thread(target=writeWarnLog,args=(f))
t2=threading.Thread(target=writeErrorLog,args=(f))

刚开始我遇到这个问题,感觉很奇怪,明明是给了参数的,但是为什么还说,没有提供参数呢??代码逻辑上也没有错啊,搞不定!
然后查询了Python的API,发现关于args的说明是这样的:
[color=red]args is the argument tuple for the target invocation. Defaults to ().[/color]
就是说,这个args是个元组,必须传一个元组,而我这里给的(f)并不是一个元组,如果元组只有一个元素时,格式应该是(element,),不能少了那个逗号,也就是说上门两行代码应该写成如下格式:

t1=threading.Thread(target=writeWarnLog,args=(f,))
t2=threading.Thread(target=writeErrorLog,args=(f,))

修改之后,执行成功,不小心导致的,坑爹啊!
但是!
我试了一下,如果把那两行代码中,参数改为数组格式,照样执行成功,即:

t1=threading.Thread(target=writeWarnLog,args=[f])
t2=threading.Thread(target=writeErrorLog,args=[f])

这个就有点更坑爹,目前还不得其奥妙.........
<think>好的,用户想了解如何使用Python进行多线程文件操作,特别是需要一个例子。首先,我需要回忆Python中的多线程模块,比如threading。同时,用户可能关心线程安全的问题,因为同时文件可能导致数据混乱或损坏。 接下来,应该考虑如何确保多个线程安全地入同一个文件。常见的解决方案是使用锁机制,比如threading.Lock(),在文件前获取锁,入完成后释放锁,这样可以避免多个线程同时文件。另外,可能需要提到Queue模块,用队列来管理入任务,让线程从队列中获取任务并按顺序处理,这也能有效避免竞争条件。 然后,用户可能需要一个具体的代码示例。需要展示如何创建线程,如何使用锁,以及如何将数据文件。代码的结构应该清晰,包含必要的注释,说明每一步的作用。比如,定义一个入函数,使用with lock语句来保证同一时间只有一个线程执行操作。 还要注意文件打开的模式,比如使用追加模式'a',这样每次入不会覆盖之前的内容。另外,要提醒用户在使用多线程时可能遇到的性能问题,比如GIL(全局解释器锁)对CPU密集型任务的影响,但对于I/O密集型任务(如文件入),多线程仍然有效。 最后,生成相关问题时要围绕多线程文件的扩展问题,比如性能优化、异常处理、队列使用、与其他操作的结合等。这样用户可以根据提供的信息进一步探索相关主题。</think>### 如何用Python实现多线程文件操作? #### 核心思路 多线程文件的关键在于**线程同步**,避免多个线程同时入导致数据混乱。Python的`threading`模块配合锁机制(`Lock`)或队列(`Queue`)可实现安全的文件操作[^2][^3]。 #### 分步实现 1. **使用`threading.Lock`控制入顺序** 通过锁保证同一时间仅一个线程访问文件: ```python import threading # 创建线程锁 file_lock = threading.Lock() def write_to_file(text, filename="output.txt"): with file_lock: # 自动获取/释放锁 with open(filename, 'a') as f: # 追加模式 f.write(text + "\n") # 创建10个线程模拟并发入 threads = [] for i in range(10): t = threading.Thread(target=write_to_file, args=(f"Thread {i} data",)) threads.append(t) t.start() for t in threads: t.join() ``` 2. **使用`queue.Queue`管理入任务** 通过队列解耦任务生成与执行,提升系统稳定性: ```python import threading import queue task_queue = queue.Queue() def worker(filename="output.txt"): while True: text = task_queue.get() if text is None: # 终止信号 break with open(filename, 'a') as f: f.write(text + "\n") task_queue.task_done() # 启动3个工作线程 threads = [] for _ in range(3): t = threading.Thread(target=worker) t.start() threads.append(t) # 添加任务 for i in range(10): task_queue.put(f"Task {i} data") task_queue.join() # 等待队列清空 # 终止线程 for _ in range(3): task_queue.put(None) for t in threads: t.join() ``` #### 注意事项 - **文件模式选择**:使用追加模式`a`避免覆盖,或`w+`模式需更严格同步 - **异常处理**:建议在入函数中添加`try-except`块捕获`IOError` - **性能权衡**:磁盘I/O速度可能成为瓶颈,过度线程数反会降低效率 - **GIL限制**:Python全局解释器锁对CPU密集型任务有限制,但I/O操作不受影响[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值