python文件在线程中写入而不是写入所有行

python文件在线程中写入而不是写入所有行,python,multithreading,Python,Multithreading,我测试了我的代码输出并对其排序,但我没有像预期的那样使用0-1999,因为缺少行。我的代码线程不安全吗?请建议如何在我的代码中添加线程锁,我发现我的Exception all没有抛出任何错误,对吗?谢谢 import time, threading, random class MyThreadWithArgs(threading.Thread): def __init__(self, string): threading.Thread.__init__(self)

我测试了我的代码输出并对其排序,但我没有像预期的那样使用0-1999,因为缺少行。我的代码线程不安全吗?请建议如何在我的代码中添加线程锁,我发现我的Exception all没有抛出任何错误,对吗?谢谢

import time, threading, random

class MyThreadWithArgs(threading.Thread):
    def __init__(self, string):
        threading.Thread.__init__(self)
        self.string = string

    def run(self):
        try:
            fo = open("foo.np2", "a")
            fo.write( self.string )
            fo.write( '\n' )
            time.sleep(random.uniform(0.1, 0.9))
            fo.close()
        except:
            print ("error logging " + self.string)

ttl_threads = 2000
for i in range(ttl_threads):
    t = MyThreadWithArgs(string = str(i))
    t.start()

这可能会像预期的那样起作用。为简单起见,删除了异常处理

import time, threading, random

class MyThreadWithArgs(threading.Thread):
    def __init__(self, string):
        threading.Thread.__init__(self)
        self.string = string

    def run(self):
        fo.write( self.string + '\n' )
        time.sleep(random.uniform(0.1, 0.9))

fo = open("foo.np2", "a")
ttl_threads = 2000
for i in range(ttl_threads):
    t = MyThreadWithArgs(string = str(i))
    t.start()
在原始程序中,您以附加模式打开同一文件的多个句柄。每个句柄都维护自己的指针,指向它认为是文件结尾的地方,但是线程0可以在线程1开始写入之前修改文件。线程1仍将写入调用open时文件结尾的位置

通过只打开一个文件描述符,您只有一个文件结束指针,并且底层的
write
系统调用可能通过操作系统内部锁定机制在给定的文件描述符上重入

我所做的另一个更改是将两个调用中的字符串连接到
write()
,因为作为两个单独的调用,您为调度提供了在系统调用之间切换线程的机会,并且很可能在一行中有两个
self.string
值,然后在一行中有两个或更多的
\n
字符串


我不知道python对
write
有什么(如果有的话)保证,我只知道
write()
在大多数POSIX平台上如何在C中工作。如果您想要保证,请查看python文档,或者用锁围绕
write()
调用。

except all
在python中并不意味着什么特殊,如果必须输入
except
块,解释器将阻塞它。要捕获所有异常,请使用除之外的普通
。这是您的实际代码吗<代码>ttl_线程=2000,适用于范围内的i(ttl_线程):
对我来说似乎不是有效的语法。@Kevin将两行分开,修复了使用
打开(…)作为…
打开文件的问题。如果try块中有错误,
fo
将不会关闭。当我运行代码时,会出现“打开的文件太多”异常。也许你可以在主线程中打开该文件一次,这样你的其他数千个线程就不必自己打开了。Brian,回答得很好。我可以把它说得更清楚。快速提问——为了争论的缘故。您使文件处理一个全局变量(有效)。您是否也可以将文件句柄传递给构造函数?或者这个伪(或实际)克隆引用?是的,您应该能够将文件描述符传递到构造函数中。
import time, sys, threading, random

class MyThreadWithArgs(threading.Thread):
    def __init__(self, i, global_msg_i):
        threading.Thread.__init__(self)
        self.i = i
        self.global_msg_i = global_msg_i
    def run(self):
        global global_msg
        try:
            i = self.i
            global_msg_i = self.global_msg_i
            time.sleep(random.uniform(0.1, 0.9))
            print (i)
            global_msg[global_msg_i] = str(i)
            time.sleep(random.uniform(0.1, 0.9))
        except:
            pass
        finally:
            pass

def reset_threads_global_msg():
    global threads, global_msg, global_msg_i, ttl_threads
    threads = []
    global_msg = [None] * ttl_threads
    global_msg_i = 0

def start_join_threads_write_global_msg():
    global threads, global_msg
    for x in threads:
        x.start()
        time.sleep(0.001) # avoid thread create error when creating too fast?!
    [x.join() for x in threads]
    fo = open("foo_test.np++", "a")
    for msg in global_msg:
        if msg is not None:
            fo.write( msg + '\n')
    fo.close()

ttl_threads = 200
reset_threads_global_msg()
for ttl_threads_i in range(1, ttl_threads + 1):
    t = MyThreadWithArgs(i = ttl_threads_i, global_msg_i = global_msg_i)
    threads.append(t)
    global_msg_i += 1
start_join_threads_write_global_msg()
reset_threads_global_msg()