Модуль Python os.chmod (файл, 664) не змінює дозвіл на rw-rw-r— but -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 такий важливий для отримання правильного результату?


33
Октальна. Октальна. Октальна.
Коул Джонсон

6
Я відкрив проблему для документації на python на bugs.python.org/issue25377, оскільки це повинно бути зрозуміло в документах.
Карл Ріхтер

Відповіді:


130

Знайшли це на іншому форумі

Якщо вам цікаво, чому важливий цей провідний нуль, це тому, що дозволи встановлюються як вісімкове ціле число, і Python автоматично розглядає будь-яке ціле число з провідним нулем як вісімкове. Так os.chmod ("файл", 484) (у десятковій формі) дав би той самий результат.

Те, що ви робите, - це передавання того, 664що знаходиться в восьмериці1230

У вашому випадку вам знадобиться

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

[Оновлення] Примітка. Для Python 3 у вас є префікс 0o (нуль о). EG,0o666


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 (нуль о).
Мауг каже, що повернемо Моніку

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/…
Піт

Робота для мене tks!
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

Я знаю, що це пітон, але навряд чи це може бути
гірше

2

Якщо ви бажаєте, щоб дозволи збереглися в рядку, тоді зробіть

s = '660'
os.chmod(file_path, int(s, base=8))

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.