Модуль Python os.chmod (файл, 664) не изменяет разрешение на rw-rw-r— но -w - wx ----

111

Недавно я использую модуль Python os, когда я пытался изменить права доступа к файлу, я не получил ожидаемого результата. Например, я намеревался изменить разрешение на rw-rw-r--,

os.chmod("/tmp/test_file", 664)

Право собственности на самом деле -w - wx --- (230)

--w--wx--- 1 ag ag 0 Mar 25 05:45 test_file

Однако, если я изменю в коде с 664 на 0664, результат будет именно тем, что мне нужно, например

os.chmod("/tmp/test_file", 0664)

Результат:

-rw-rw-r-- 1 ag ag 0 Mar 25 05:55 test_file

Может ли кто-нибудь помочь объяснить, почему этот ведущий 0 так важен для получения правильного результата?

AplusG
источник
33
Восьмеричный. Восьмеричный. Восьмеричный.
Коул Джонсон
6
Я открыл проблему для документации python на bugs.python.org/issue25377, потому что это должно быть ясно из документации.
Карл Рихтер,

Ответы:

130

Нашел это на другом форуме

Если вам интересно, почему этот ведущий ноль важен, это потому, что разрешения устанавливаются как восьмеричное целое число, а Python автоматически обрабатывает любое целое число с ведущим нулем как восьмеричное. Таким образом, os.chmod ("file", 484) (в десятичном формате) даст тот же результат.

То, что вы делаете, - это передача, 664которая в восьмеричном формате1230

В вашем случае вам понадобится

os.chmod("/tmp/test_file", 436)

[Обновление] Обратите внимание, что для Python 3 у вас есть префикс с 0o (ноль о). НАПРИМЕР,0o666

RedBaron
источник
1
Спасибо, но меня все еще смущает, что 484 в десятичном формате означает 744 в восьмеричном, что имеет смысл в теме, о которой вы упомянули на форуме. Однако, если я дам 644 в десятичной системе счисления, в восьмеричной системе получится 1204. Как 1204 соотносится с 230 в восьмеричной системе счисления?
AplusG
2
@AplusG: 1это не исключено ! Это бит липкости / setuid / setgid, а 1 означает sticky. Используя, ls -lвы можете заметить, что разрешения теперь включают Tв себя ...
MestreLion
2
проще добавить 0 и сделать его восьмеричным :)
radtek
10
Обратите внимание, что для Python 3 у вас есть префикс с 0o (ноль oh).
Mawg говорит восстановить Монику
1
Я использую 0o в python 2.7.10
Wyrmwood
125

Итак, для людей, которым нужна семантика, подобная:

$ chmod 755 somefile

Использование:

$ python -c "import os; os.chmod('somefile', 0o755)"

Если ваш Python старше 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
Дима
источник
12
Формат python3 также работает в python 2.7.9. Более ранние версии не проверял.
Фред Митчелл,
3
Синтаксис Python 3 возвращается к Python 2.6 docs.python.org/3/whatsnew/…
Пит,
Работай у меня спасибо!
LandiLeite
Вероятно, должно быть 00755, просто чтобы прояснить, где идут биты suid / sgid / sticky, в случае, если какой-то более поздний разработчик придет и захочет использовать этот старый скрипт, например, sgid с, 2755но затем не сможет понять, почему завивки полностью облажались. ;)
dannysauer
10

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

разрешения немного маски, например, rwxrwx---находится 111111000в двоичной системе , и это очень легко группы биты на 3 , чтобы преобразовать в восьмеричном, чем стоимости десятичного представления.

0644(восьмеричный) находится 0.110.100.100в двоичном формате (я добавил точки для удобства чтения) или, как вы можете вычислить, 420в десятичном.

леник
источник
5

Используйте символы разрешений вместо цифр

Вашей проблемы можно было бы избежать, если бы вы использовали более семантически названные символы разрешений, а не необработанные магические числа, например, для 664:

#!/usr/bin/env python3

import os
import stat

os.chmod(
    'myfile',
    stat.S_IRUSR |
    stat.S_IWUSR |
    stat.S_IRGRP |
    stat.S_IWGRP |
    stat.S_IROTH
)

Это задокументировано на https://docs.python.org/3/library/os.html#os.chmod, а имена совпадают со значениями API POSIX C, задокументированными на man 2 stat.

Еще одним преимуществом является большая переносимость, как указано в документации:

Примечание: Хотя поддержка Windows chmod()можно установить только для чтения только флаг файла с ним ( с помощью stat.S_IWRITEи stat.S_IREADконстант или соответствующего целого значения). Все остальные биты игнорируются.

chmod +xдемонстрируется на странице: Как сделать простой "chmod + x" изнутри Python?

Протестировано в Ubuntu 16.04, Python 3.5.2.

Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
1
Это правильный способ решения проблемы.
carthurs
Я знаю это по-питонски, но вряд ли это может быть более уродливым :)
Tomasz Swider
2

Если у вас есть желаемые разрешения, сохраненные в строке, выполните

s = '660'
os.chmod(file_path, int(s, base=8))
mc.dev
источник
0

Использование битовых масок stat. * Действительно кажется мне наиболее переносимым и явным способом сделать это. Но с другой стороны, я часто забываю, как лучше с этим справиться. Итак, вот пример маскировки разрешений «группа» и «другие» и оставления разрешений «владельца» нетронутыми. Использование битовых масок и вычитания - полезный паттерн.

import os
import stat
def chmodme(pn):
    """Removes 'group' and 'other' perms. Doesn't touch 'owner' perms."""
    mode = os.stat(pn).st_mode
    mode -= (mode & (stat.S_IRWXG | stat.S_IRWXO))
    os.chmod(pn, mode)
Джейсон Дрю
источник