Yes, chmod is usually not working on Windows.
It is better to use the proper tools from command line: cacls for old versions of windows (Windows XP or below), or icacls for most versions of Windows.
The following code could allow to change permissions (with an additional context manager to change temporarily if needed):
"""
Prototype of script to modify access rights with "icacls" in Windows
"""
from contextlib import contextmanager
from enum import Enum
from subprocess import check_output
from pathlib import Path
from typing import Generator, List
class AccessRight(Enum):
    """Access Rights for files/folders"""
    DELETE = "D"
    FULL = "F"  # Edit Permissions + Create + Delete + Read + Write
    NO_ACCESS = "N"
    MODIFY = "M"  # Create + Delete + Read + Write
    READ_EXECUTE = "RX"
    READ_ONLY = "R"
    WRITE_ONLY = "W"
@contextmanager
def set_access_right(file: Path, access: AccessRight) -> Generator[Path, None, None]:
    """Context Manager to temporarily set a given access rights to a file and reset"""
    def cmd(access_right: AccessRight) -> List[str]:
        return [
            "icacls",
            str(file),
            "/inheritance:r",
            "/grant:r",
            f"Everyone:{access_right.value}",
        ]
    try:
        check_output(cmd(access))
        yield file
    finally:
        check_output(cmd(AccessRight.FULL))
# We create a file (if it does not exist) with empty content
toto = Path("toto.txt")
toto.touch()
# We temporarily set access rights of the
with set_access_right(toto, AccessRight.WRITE_ONLY) as path:
    path.write_text("My name is Toto")
    try:
        content = path.read_text()
        print(f":( Should not be able to read content of file but read: {content}")
    except PermissionError:
        print("Cannot read toto: YEAH!")
# We check that access rights have been restored (and delete the file to stay clean)
print(path.read_text())
toto.unlink()
[Edit March 2023]  -> Alternate solution using os.chmod, which might be more complex but is cross-platform
Based on a remark from @L4ZZA and from this answer, we could also use the permissions defined in stat:
import os
import stat
# If you want to set new permisions (i.e. replace)
os.chmod('my_file.txt', <stat mask>)
# If you want to add new permissions
st = os.stat('somefile')
os.chmod('my_file.txt', st.st_mode | <stat mask>)
With the mask stat mask being one or several of the following (if several, join them with a |):
- stat.S_ISUID: set UID bit
- stat.S_ISGID: set GID bit
- stat.S_ENFMT: file locking enforcement
- stat.S_ISVTX: sticky bit
- stat.S_IREAD: Unix V7 synonym for S_IRUSR
- stat.S_IWRITE: Unix V7 synonym for S_IWUSR
- stat.S_IEXEC: Unix V7 synonym for S_IXUSR
- stat.S_IRWXU: mask for owner permissions
- stat.S_IRUSR: read by owner
- stat.S_IWUSR: write by owner
- stat.S_IXUSR: execute by owner
- stat.S_IRWXG: mask for group permissions
- stat.S_IRGRP: read by group
- stat.S_IWGRP: write by group
- stat.S_IXGRP: execute by group
- stat.S_IRWXO: mask for others (not in group) permissions
- stat.S_IROTH: read by others
- stat.S_IWOTH: write by others
- stat.S_IXOTH: execute by others