python file writing in threads not writing all lines
Question: I tested my code output and sort it, but I am not having 0-1999 as expected,
lines is missing. Is my code thread unsafe? please suggest how to add thread
lock in my code, and i found that my except all doesn't throw any errors, is
it correct? thanks

    
    
    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()
    


Answer: This will probably work as expected. Exception handling removed for
simplicity.

    
    
    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()
    

In the original program, you're opening multiple handles to the same file in
append mode. Each of handles maintains its own pointer to what it thinks is
the end of the file, but it's possible for thread-0 to modify the file before
thread-1 gets to write. thread-1 will still write to where the end-of-file
_WAS_ when it called open.

By keeping only one file descriptor open, you have only one end-of-file
pointer and the underlying `write` system call is _probably_ reentrant on a
given file descriptor via OS internal locking mechanisms.

The other change I made was concatenating the strings from the two calls to
`write()` because as two separate calls, you're giving the schedule a chance
to switch threads in between system calls, and likely to end up with two
`self.string` values in a row followed by two or more `\n` strings in a row.

I don't know off the top of my what (if any) guarantees python makes about
`write`, I'm just going off what I know about how `<unistd.h> write()` works
in C on most POSIX platforms. If you want guarantees, check the python
documentation, or surround the `write()` call with a lock.

