Windows
That such a demo should be sufficient. The file opens with the 0 flag in dwShareMode , which means
If you request it, delete, read, or write access.
import multiprocessing import time import ctypes from ctypes.wintypes import DWORD CREATE_ALWAYS = 2 GENERIC_WRITE = 0x40000000 def worker(word,i): print('Started {}'.format(i)) try: handle = ctypes.windll.kernel32.CreateFileA("file.txt", GENERIC_WRITE, 0, None, CREATE_ALWAYS, 0, None ) if handle == -1: # ctypes.WinError sets up an GetLastError API call for windows as an Python OSError exception. # So we use this to raise the error to our caller. raise ctypes.WinError() print('Process {}: File opened successfully'.format(i)) time.sleep(2) written = DWORD() ctypes.windll.kernel32.WriteFile(handle, word, len(word), ctypes.byref(written), None) print('Process {}: Write completed'.format(i)) ctypes.windll.kernel32.CloseHandle(handle) except Exception as e: print('Process {}: Cannot access file'.format(i)) print('{}: {}'.format(type(e).__name__,e.args)) print('Finished {}'.format(i)) if __name__ == '__main__': for i in range(2): multiprocessing.Process(target=worker, args=('worker{}'.format(i),i)).start()
Displays:
Started 0 Process 0: File opened successfully Started 1 Process 1: Cannot access file PermissionError: (13, 'The process cannot access the file because it is being used by another process.', None, 32) Finished 1 Process 0: Write completed Finished 0
Posix
Now there is nothing at hand to test, but it should work. :)
Here you have to explicitly lock the file after opening. And since this is a blocking operation, we do a timeout using the signal module and the corresponding binding.
import multiprocessing import time import signal, errno from contextlib import contextmanager import fcntl @contextmanager def timeout(seconds): def timeout_handler(signum, frame): pass original_handler = signal.signal(signal.SIGALRM, timeout_handler) try: signal.alarm(seconds) yield finally: signal.alarm(0) signal.signal(signal.SIGALRM, original_handler) def worker(word,i): print('Started {}'.format(i)) with timeout(1): try: f = open("file.txt", "w") print('Process {}: File opened successfully'.format(i)) fcntl.flock(f.fileno(), fcntl.LOCK_EX) print('Process {}: File locked successfully'.format(i)) time.sleep(3) f.write(word) print('Process {}: Write completed'.format(i)) fcntl.flock(f.fileno(), fcntl.LOCK_UN) print('Process {}: File unlocked'.format(i)) f.close() except IOError as e: if e.errno != errno.EINTR: raise e print('Process {}: Cannot access file'.format(i)) print('Finished {}'.format(i)) if __name__ == '__main__': for i in range(2): multiprocessing.Process(target=worker, args=('worker{}'.format(i),i)).start()
start()method - Mr Morgan