В Windows «os.chmod» в Python не работает должным образом

#python #windows #chmod

#python #Windows #chmod

Вопрос:

Я пытаюсь установить права доступа к файлам в Python os.chmod в Windows.

Я могу успешно удалить доступ на запись, но не доступ на чтение:

 >>> import os

>>> import stat

>>> from pathlib import Path

>>> toto = Path("toto.txt")

>>> toto.write_text("Hello")
5


>>> toto.read_text()
'Hello'


>>> os.chmod(toto, toto.stat().st_mode amp; ~stat.S_IWUSR)

>>> toto.write_text("Hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:python37-32libpathlib.py", line 1208, in write_text
    with self.open(mode='w', encoding=encoding, errors=errors) as f:
  File "c:python37-32libpathlib.py", line 1176, in open
    opener=self._opener)
  File "c:python37-32libpathlib.py", line 1030, in _opener
    return self._accessor.open(self, flags, mode)
PermissionError: [Errno 13] Permission denied: 'toto.txt'

[Errno 13] Permission denied: 'toto.txt'

>>> os.chmod(toto, stat.S_IRWXU)

>>> toto.write_text("Hello")
5


>>> os.chmod(toto, toto.stat().st_mode amp; ~stat.S_IRUSR)

>>> toto.read_text()
'Hello'
 

Последняя строка должна была вызвать ошибку, потому что у файла не должно быть прав на чтение.

Как решить проблему?

Ответ №1:

Лучший способ установить права доступа в Windows — использовать icacls .

Этот код может помочь в этом:

 """
Example 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"


def change_access_rights(file: Path, access: AccessRight) -> None:
    """Change Access Rights of a given file"""

    def cmd(access_right: AccessRight, mode="grant:r") -> List[str]:
        return [
            "icacls",
            str(file),
            "/inheritance:r",
            f"/{mode}",
            f"Everyone:{access_right.value}",
        ]

    if access == AccessRight.NO_ACCESS:
        check_output(cmd(AccessRight.FULL, mode="deny"))
    else:
        check_output(cmd(access))


@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"""

    try:
        change_access_rights(file, access)
        yield file

    finally:
        change_access_rights(file, 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
print(path.read_text())

change_access_rights(toto, AccessRight.NO_ACCESS)
try:
    toto.write_text("My name is Toto")
    print(f":( Should not be able to write in file")
except PermissionError:
    print("NO ACCESS to toto: YEAH!")

# We check that access rights have been restored (and delete the file to stay clean)
change_access_rights(toto, AccessRight.FULL)
toto.write_text("The end...")
print(toto.read_text())

change_access_rights(toto, AccessRight.DELETE)
toto.unlink()