I have a programm on windows (Win7) that writes to a txt file every x seconds. Now I have a python script that reads this txt File every x seconds. When the python script reads the File and at the same time the other Program wants to write to that file - The writing program crashes (and displays permission error). Since I cant modify the way the Program writes to the txt file, I have to try to open the txt File without blocking the writing program. Does someone know what I could do in this situation (reading without blocking) I would be very happy for every tip on this topic!
The code for the Program that tries to read the File goes something like this:
with codecs.open(datapath, "r", 'utf-16') as raw_data:
raw_data_x = raw_data.readlines()
I have to open the File with "codecs" because its in unicode.
After a long time, I managed to create a function that does it for you in ctypes. Keep in mind this will only work if the process didn't acquire "Exclusive" access. If it did, you're out of luck and will need to use a shadow copy service like shown here or implemented here.
Anyway, here you go:
import ctypes
from ctypes import wintypes
import os
import msvcrt
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
ACCESS_MODES = {
"r": GENERIC_READ,
"w": GENERIC_WRITE,
"r+": (GENERIC_READ|GENERIC_WRITE)
}
OPEN_MODES = {
"r": OPEN_EXISTING,
"w": OPEN_ALWAYS,
"r+": OPEN_ALWAYS,
}
def open_file_nonblocking(filename, access):
# Removes the b for binary access.
internal_access = access.replace("b", "")
access_mode = ACCESS_MODES[internal_access]
open_mode = OPEN_MODES[internal_access]
handle = wintypes.HANDLE(ctypes.windll.kernel32.CreateFileW(
wintypes.LPWSTR(filename),
wintypes.DWORD(access_mode),
wintypes.DWORD(2|1), # File share read and write
ctypes.c_void_p(0),
wintypes.DWORD(open_mode),
wintypes.DWORD(0),
wintypes.HANDLE(0)
))
try:
fd = msvcrt.open_osfhandle(handle.value, 0)
except OverflowError as exc:
# Python 3.X
raise OSError("Failed to open file.") from None
# Python 2
# raise OSError("Failed to open file.")
return os.fdopen(fd, access)
The function opens the file while sharing the read and write handle allowing multiple access. It then converts the handle to a normal python file object.
Make sure to close the file when you finish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With