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?


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


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

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.


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.


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))

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.