В целом, способ вот такой:
>>> path = '...'Теперь разберёмся что всё это значит.
>>> print(oct(os.stat(path).st_mode & 0o777).split('o')[-1])
'755'
До того как мы сделали split() строка была следующего вида:
0o755
Что это за тип данных? Это тип int в восмиричной системе исчисления. Для преобразования в такой формат есть builtin функция oct()>>> oct(493)Как видите, результат возвращается виде строки. Но это не мешает нам создавать переменные синтаксисом восьмеричных чисел, то есть с префиксом 0o. Хотя, при распечатке мы всё равно получим int.
'0o755'
>>> x = 0o777Преобразовать эту строку в int можно функцией int(), указав базис 8
>>> print(x)
511
>>> int('0o755', 8)
493
Теперь посмотрим что нам возвращает os.stat>>> perm = os.stat(path).st_modeПреобразуем в oct
33261
>>> oct(perm)Уже почти то что надо. Чтобы оставить только нужное, отрезаем лишнее с помощью оператора & (AND).
'0o100755'
Для этого последние 3 значения ставим максимальными, остальные нулевыми.
>>> perm & 0o777Оператор работает с бинарным представлением чисел, то есть операция была вот такая:
493
0b100000111101101Вспоминаем побитовые операторы
& 0b111111111
= 0b111101101
Остаётся преобразовать в восьмеричное представление и убрать префикс
>>> oct(493)Именно в таком виде пермишены файла в коде обычно не используются.
'0o755'
>>> oct(493).split('o')[-1]
'755'
Хранить и использовать их удобно в виде восьмеричного int
os.chmod(path, 0o755)или строки
os.chmod(path, int('0o755', 8))
А зачем в строке если достаточно в int? Наприрмер чтобы в json была удобочитаемая запись. Так как сериализатор запишет восьмеричное число как обычный десятичный int>>> json.dumps(0o755)Поэтому для удобства пишем его строкой а потом преобразуем в восьмеричный int.
'493'
#tricks