Moduł Pythona os.chmod (plik, 664) nie zmienia uprawnień na rw-rw-r— ale -w - wx ----

111

Ostatnio używam systemu operacyjnego Python, gdy próbowałem zmienić uprawnienia pliku, nie uzyskałem oczekiwanego wyniku. Na przykład zamierzałem zmienić pozwolenie na rw-rw-r--,

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

Uprawnienie do własności to w rzeczywistości -w - wx --- (230)

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

Jeśli jednak zmienię w kodzie 664 na 0664 to wynik jest właśnie tym, czego potrzebuję np

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

Wynik to:

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

Czy ktoś mógłby pomóc wyjaśnić, dlaczego to wiodące 0 jest tak ważne dla uzyskania prawidłowego wyniku?

AplusG
źródło
33
Ósemkowe. Ósemkowe. Ósemkowe.
Cole Johnson,
6
Otworzyłem problem dotyczący dokumentacji Pythona na bugs.python.org/issue25377, ponieważ powinno to być jasne z dokumentacji.
Karl Richter,

Odpowiedzi:

130

Znalazłem to na innym forum

Jeśli zastanawiasz się, dlaczego to wiodące zero jest ważne, to dlatego, że uprawnienia są ustawiane jako ósemkowe liczby całkowite, a Python automagicznie traktuje każdą liczbę całkowitą z wiodącym zerem jako liczbę ósemkową. Więc os.chmod ("plik", 484) (dziesiętnie) dałby ten sam wynik.

To, co robisz, to mijanie, 664co jest ósemkowe1230

W twoim przypadku potrzebujesz

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

[Aktualizacja] Uwaga, dla Pythona 3 masz prefiks 0o (zero oh). NA PRZYKŁAD,0o666

RedBaron
źródło
1
Dzięki, ale nadal jestem zdezorientowany, że 484 dziesiętnie oznacza 744 ósemkowo, co ma sens w wątku, o którym wspomniałeś na forum. Jeśli jednak podam liczbę 644 dziesiętnie, to liczba ósemkowa wynosi 1204. W jaki sposób 1204 odnosi się do liczby 230 ósemkowej?
AplusG
2
@AplusG: nie1 jest odrzucany! To jest bit sticky / setuid / setgid, a 1 oznacza . Używając możesz zauważyć, że uprawnienia obejmują teraz na końcu ...stickyls -lT
MestreLion,
2
łatwiej dodać 0 i uczynić to ósemkowym :)
radtek
10
Uwaga, dla Pythona 3 masz prefiks 0o (zero oh).
Mawg mówi, że przywróć Monikę
1
Używam 0o w Pythonie 2.7.10
Wyrmwood
125

Więc dla ludzi, którzy chcą semantyki podobnej do:

$ chmod 755 somefile

Posługiwać się:

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

Jeśli Twój Python jest starszy niż 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
Dima
źródło
12
Format python3 działa również w pythonie 2.7.9. Nie sprawdzałem wcześniejszych wersji.
Fred Mitchell
3
Składnia Pythona 3 działa z powrotem do Pythona 2.6 docs.python.org/3/whatsnew/ ...
Pete
Pracuj dla mnie tks!
LandiLeite
Prawdopodobnie powinno być 00755, tylko po to, aby wyjaśnić, gdzie idą bity suid / sgid / sticky, na wypadek, gdyby przyszedł jakiś późniejszy programista i chciałby, aby ten stary skrypt używał, na przykład, sgid with, 2755ale potem nie może zrozumieć, dlaczego perms są całkowicie schrzanione. ;)
dannysauer
10

wiodący 0oznacza, że ​​jest to stała ósemkowa , a nie dziesiętna. i potrzebujesz ósemkowego do zmiany trybu pliku.

uprawnienia to maska ​​bitowa, na przykład rwxrwx---jest 111111000binarna i bardzo łatwo jest pogrupować bity po 3, aby przekonwertować je na liczbę ósemkową, niż obliczyć reprezentację dziesiętną.

0644(ósemkowe) jest 0.110.100.100binarne (dodałem kropki dla czytelności) lub, jak możesz obliczyć, 420dziesiętnie.

Lenik
źródło
5

Użyj symboli uprawnień zamiast liczb

Twój problem zostałby uniknięty, gdybyś użył bardziej semantycznie nazwanych symboli uprawnień zamiast surowych liczb magicznych, np. Dla 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
)

Jest to udokumentowane na https://docs.python.org/3/library/os.html#os.chmod, a nazwy są takie same, jak wartości POSIX C API udokumentowane w man 2 stat.

Kolejną zaletą jest większa przenośność, jak wspomniano w dokumentach:

Uwaga: Chociaż system Windows obsługuje chmod(), możesz ustawić flagę tylko do odczytu pliku (za pomocą stałych stat.S_IWRITEi stat.S_IREADlub odpowiadającej im wartości całkowitej). Wszystkie inne bity są ignorowane.

chmod +xjest zademonstrowane na: Jak wykonać proste „chmod + x” z poziomu Pythona?

Testowane w Ubuntu 16.04, Python 3.5.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
1
To jest właściwy sposób rozwiązania problemu.
carthurs
Wiem to po pythonie, ale nie może być brzydszy :)
Tomasz Swider
2

Jeśli masz żądane uprawnienia zapisane w łańcuchu znaków, zrób to

s = '660'
os.chmod(file_path, int(s, base=8))
mc.dev
źródło
0

Używanie masek stat. * Bit wydaje mi się najbardziej przenośnym i jednoznacznym sposobem na zrobienie tego. Ale z drugiej strony często zapominam, jak najlepiej sobie z tym poradzić. Oto przykład zamaskowania uprawnień „grupy” i „innych” oraz pozostawienia nietkniętych uprawnień „właściciela”. Używanie masek bitowych i odejmowania jest przydatnym wzorcem.

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)
Jason Drew
źródło