El módulo de Python os.chmod (archivo, 664) no cambia el permiso a rw-rw-r— pero -w - wx ----

111

Recientemente, estoy usando el sistema operativo del módulo Python, cuando intenté cambiar el permiso de un archivo, no obtuve el resultado esperado. Por ejemplo, tenía la intención de cambiar el permiso a rw-rw-r--,

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

El permiso de propiedad es en realidad -w - wx --- (230)

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

Sin embargo, si cambio 664 a 0664 en el código, el resultado es justo lo que necesito, por ejemplo

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

El resultado es:

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

¿Alguien podría ayudar a explicar por qué ese 0 inicial es tan importante para obtener el resultado correcto?

AplusG
fuente
33
Octal. Octal. Octal.
Cole Johnson
6
Abrí un problema para la documentación de Python en bugs.python.org/issue25377 porque eso debería quedar claro en los documentos.
Karl Richter

Respuestas:

130

Encontré esto en un foro diferente

Si se pregunta por qué es importante ese cero a la izquierda, es porque los permisos se establecen como un entero octal y Python trata automáticamente cualquier número entero con un cero a la izquierda como octal. Entonces os.chmod ("file", 484) (en decimal) daría el mismo resultado.

Lo que estás haciendo es pasar 664que en octal es1230

En tu caso necesitarías

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

[Actualización] Nota, para Python 3 tienes el prefijo con 0o (cero oh). P.EJ,0o666

RedBaron
fuente
1
Gracias, pero todavía estoy confundido de que 484 en decimal significa 744 en octal, lo que tiene sentido en el hilo que mencionaste en el foro. Sin embargo, si doy 644 en decimal, pasa a 1204 en octal. ¿Cómo se relaciona 1204 con 230 en octal?
AplusG
2
@AplusG: la 1se no descartan! Ese es el bit sticky / setuid / setgid, y 1 significa sticky. El uso ls -lpuede notar que los permisos ahora incluyen un Tal final ...
MestreLion
2
es más fácil agregar el 0 y hacerlo octal :)
radtek
10
Tenga en cuenta que para Python 3 tiene un prefijo con 0o (cero oh).
Mawg dice reinstalar a Monica
1
Uso 0o en Python 2.7.10
Wyrmwood
125

Entonces, para las personas que quieren una semántica similar a:

$ chmod 755 somefile

Utilizar:

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

Si su Python es anterior a 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
Dima
fuente
12
El formato python3 también funciona en python 2.7.9. No he comprobado versiones anteriores.
Fred Mitchell
3
La sintaxis de Python 3 funciona de nuevo a Python 2.6 docs.python.org/3/whatsnew/…
Pete
¡Trabaja para mí tks!
LandiLeite
Probablemente debería ser 00755, solo para dejar en claro a dónde van los bits suid / sgid / sticky, en caso de que algún desarrollador posterior venga y quiera hacer que este antiguo script use, por ejemplo, sgid con 2755pero luego no puedo entender por qué las permanentes están completamente arruinadas. ;)
dannysauer
10

inicial 0significa que es una constante octal , no decimal. y necesita un octal para cambiar el modo de archivo.

los permisos son una máscara de bits, por ejemplo, rwxrwx---está 111111000en binario, y es muy fácil agrupar los bits por 3 para convertirlos al octal, que calcular la representación decimal.

0644(octal) está 0.110.100.100en binario (he agregado puntos para facilitar la lectura) o, como puede calcular, 420en decimal.

lenik
fuente
5

Use símbolos de permiso en lugar de números

Su problema se habría evitado si hubiera utilizado los símbolos de permiso con nombres más semánticos en lugar de números mágicos en bruto, por ejemplo, para 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
)

Esto está documentado en https://docs.python.org/3/library/os.html#os.chmod y los nombres son los mismos que los valores de la API POSIX C documentados en man 2 stat.

Otra ventaja es la mayor portabilidad como se menciona en los documentos:

Nota: Aunque Windows es compatible chmod(), solo puede configurar el indicador de solo lectura del archivo con él (a través de las constantes stat.S_IWRITEy stat.S_IREADo un valor entero correspondiente). Todos los demás bits se ignoran.

chmod +xse demuestra en: ¿Cómo se hace un simple "chmod + x" desde dentro de Python?

Probado en Ubuntu 16.04, Python 3.5.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
1
Ésta es la forma correcta de abordar el problema.
carthurs
Sé que esto es a la manera de Python, pero difícilmente podría ser más feo :)
Tomasz Swider
2

Si ha guardado los permisos deseados en la cadena, hágalo

s = '660'
os.chmod(file_path, int(s, base=8))
mc.dev
fuente
0

Usar las máscaras stat. * Bit me parece la forma más portátil y explícita de hacer esto. Pero, por otro lado, a menudo olvido cuál es la mejor manera de manejar eso. Entonces, aquí hay un ejemplo de enmascarar los permisos de 'grupo' y 'otros' y dejar los permisos de 'propietario' intactos. El uso de máscaras de bits y la resta es un patrón útil.

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
fuente