Locking a file in Python
Alright, so I ended up going with the code I wrote here, on my website link is dead, view on archive.org (also available on GitHub). I can use it in the following fashion:
from filelock import FileLock
with FileLock("myfile.txt"):
# work with the file as it is now locked
print("Lock acquired.")
Lock file for access on windows
You could use subprocess to open the file in notepad or excel:
import subprocess, time
subprocess.call('start excel.exe "\lockThisFile.txt\"', shell = True)
time.sleep(10) # if you need the file locked before executing the next commands, you may need to sleep it for a few seconds
or
subprocess.call('notepad > lockThisFile.txt', shell = True)
As written you need shell = True, otherwise windows will give you a syntax error.
(subprocess.Popen() works as well)
You can then close the process later using:
subprocess.call('taskkill /f /im notepad.exe') # or excel.exe
Other options include
-write some C++ code and call it from python (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx)
-call 3rd party programs with subprocess.call():
FileLocker http://www.jensscheffler.de/filelocker (https://superuser.com/questions/294826/how-to-purposefully-exclusively-lock-a-file)
Easy File Locker http://www.xoslab.com/efl.html and Dispatch (from win32com.client import Dispatch), although last choice is the most complex
Locking a txt file with python
I think lockfile should meet your needs
How To Lock Files Using Python
Use os module for this purpose.
import os
file_path = 'D:\\file.txt' # your file path
os.system(f'echo y| cacls {file_path} /P everyone:n')
I hope you got it.
Opening a file on Windows with exclusive locking in Python
For those who are interested in a Windows specific solution:
import os
import ctypes
import msvcrt
import pathlib
# Windows constants for file operations
NULL = 0x00000000
CREATE_ALWAYS = 0x00000002
OPEN_EXISTING = 0x00000003
FILE_SHARE_READ = 0x00000001
FILE_ATTRIBUTE_READONLY = 0x00000001 # strictly for file reading
FILE_ATTRIBUTE_NORMAL = 0x00000080 # strictly for file writing
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
_ACCESS_MASK = os.O_RDONLY | os.O_WRONLY
_ACCESS_MAP = {os.O_RDONLY: GENERIC_READ,
os.O_WRONLY: GENERIC_WRITE
}
_CREATE_MASK = os.O_CREAT | os.O_TRUNC
_CREATE_MAP = {NULL: OPEN_EXISTING,
os.O_CREAT | os.O_TRUNC: CREATE_ALWAYS
}
win32 = ctypes.WinDLL('kernel32.dll', use_last_error=True)
win32.CreateFileW.restype = ctypes.c_void_p
INVALID_FILE_HANDLE = ctypes.c_void_p(-1).value
def _opener(path: pathlib.Path, flags: int) -> int:
access_flags = _ACCESS_MAP[flags & _ACCESS_MASK]
create_flags = _CREATE_MAP[flags & _CREATE_MASK]
if flags & os.O_WRONLY:
share_flags = NULL
attr_flags = FILE_ATTRIBUTE_NORMAL
else:
share_flags = FILE_SHARE_READ
attr_flags = FILE_ATTRIBUTE_READONLY
attr_flags |= FILE_FLAG_SEQUENTIAL_SCAN
h = win32.CreateFileW(path, access_flags, share_flags, NULL, create_flags, attr_flags, NULL)
if h == INVALID_FILE_HANDLE:
raise ctypes.WinError(ctypes.get_last_error())
return msvcrt.open_osfhandle(h, flags)
class _FileControlAccessor(pathlib._NormalAccessor):
open = staticmethod(_opener)
_control_accessor = _FileControlAccessor()
class Path(pathlib.WindowsPath):
def _init(self) -> None:
self._closed = False
self._accessor = _control_accessor
def _opener(self, name, flags) -> int:
return self._accessor.open(name, flags)
How to filelock an entire directory?
This is an issue with how portalocker deals with files - it tries to open
them, which works when opening non-existing file in 'w'
mode, and fails in 'r'
mode.
The solution in your case is to manually create the file (and never remove it, it's a bad idea).
Writer:
with pl.Lock(p_lock, 'w'):
# do things
# don't remove the p_lock file
Reader:
p_lock.touch(exist_ok=True)
with pl.Lock(p_lock, 'r', flags=pl.LockFlags.SHARED | pl.LockFlags.NON_BLOCKING):
# do things
# don't remove the p_lock file
(and don't bother writing PID into the file, unless it's for your own debugging purpuses)
Python script to write(+lock) / read a file between 3 processes
If I am not misunderstanding, the task could be achieved by using a Lock for gaining writing access, a Semaphore to notify the processes which, having failed to gain the write Lock, will want to read the file and finally a Barrier to re-align the processes.
An Example:
import multiprocessing as mp
import time
from random import randint
def fun(lock_w, sem_r, barrier, task, filename):
me = mp.current_process()
for i in range(3):
time.sleep(randint(1, 4))
if(lock_w.acquire(block=False)):
print(me.pid, "write access")
task()
sem_r.release()
sem_r.release()
else:
sem_r.acquire()
print(me.pid, "read access")
task()
if barrier.wait() == 0:
print(me.pid, "releasing Lock")
lock_w.release()
def task1():
print("\tPerform Task 1")
def task2():
print("\tPerform Task 2")
def task3():
print("\tPerform Task 3")
lock_w = mp.Lock()
sem_r = mp.Semaphore(0)
bar = mp.Barrier(3)
t1 = mp.Process(target=fun, args=(lock_w, sem_r, bar, task1, "foo.txt", ))
t2 = mp.Process(target=fun, args=(lock_w, sem_r, bar, task2, "foo.txt", ))
t3 = mp.Process(target=fun, args=(lock_w, sem_r, bar, task3, "foo.txt", ))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
Example putput:
585 write access
Perform Task 1
586 read access
Perform Task 2
587 read access
Perform Task 3
585 releasing Lock
587 write access
Perform Task 3
586 read access
Perform Task 2
585 read access
Perform Task 1
587 releasing Lock
586 write access
Perform Task 2
585 read access
Perform Task 1
587 read access
Perform Task 3
586 releasing Lock
Python locking and unlocking file from multiple processes
- Ok first, locking a file is a platform-specific operation, so you will need to run different code for different operating systems.
- Secondly, as @Kevin said here, - "coordinating access to a single file at the OS level is fraught with all kinds of issues that you probably don't want to solve. Your best bet is have a separate process that coordinates read/write access to that file."
Related Topics
How to Pass a Variable Between Flask Pages
How to Resize an Image Using Pil and Maintain Its Aspect Ratio
How to Make One Python File Run Another
Choosing the Correct Upper and Lower Hsv Boundaries For Color Detection With'Cv::Inrange' (Opencv)
How to Fix: "Unicodedecodeerror: 'Ascii' Codec Can't Decode Byte"
Convert Python Dict into a Dataframe
Count the Frequency That a Value Occurs in a Dataframe Column
When Is "I += X" Different from "I = I + X" in Python
Adding a New Pandas Column With Mapped Value from a Dictionary
Filter Dataframe Rows If Value in Column Is in a Set List of Values
Read Subprocess Stdout Line by Line
Explanation of How Nested List Comprehension Works
How to Play Wav File in Python
Is There Any Pythonic Way to Combine Two Dicts (Adding Values For Keys That Appear in Both)
How to Concatenate Text Files in Python