O módulo Python os.chmod (arquivo, 664) não altera a permissão para rw-rw-r— mas -w - wx ----

111

Recentemente estou usando o sistema operacional do módulo Python, quando tentei alterar a permissão de um arquivo, não obtive o resultado esperado. Por exemplo, eu pretendia alterar a permissão para rw-rw-r--,

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

A permissão de propriedade é, na verdade, -w - wx --- (230)

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

No entanto, se eu alterar 664 para 0664 no código, o resultado é exatamente o que eu preciso, por exemplo

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

O resultado é:

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

Alguém poderia ajudar a explicar por que esse 0 inicial é tão importante para obter o resultado correto?

AplusG
fonte
33
Octal. Octal. Octal.
Cole Johnson
6
Abri um problema para a documentação do python em bugs.python.org/issue25377 porque isso deve estar claro nos documentos.
Karl Richter,

Respostas:

130

Encontrei isso em um fórum diferente

Se você está se perguntando por que esse zero à esquerda é importante, é porque as permissões são definidas como um inteiro octal e o Python trata automaticamente qualquer inteiro com um zero à esquerda como octal. Portanto, os.chmod ("arquivo", 484) (em decimal) daria o mesmo resultado.

O que você está fazendo é passar 664que em octal é1230

No seu caso, você precisaria

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

[Atualizar] Nota, para Python 3 você tem prefixo com 0o (zero oh). POR EXEMPLO,0o666

RedBaron
fonte
1
Obrigado, mas ainda estou confuso que 484 em decimal significa 744 em octal, o que faz sentido no tópico que você mencionou no fórum. No entanto, se eu der 644 em decimal, ele vai para 1204 em octal. Como 1204 se relaciona com 230 em octal?
AplusG
2
@AplusG: o não1 é descartado! Esse é o bit sticky / setuid / setgid e 1 significa . Usando você pode notar que as permissões agora incluem um no final ...stickyls -lT
MestreLion
2
mais fácil adicionar o 0 e torná-lo octal :)
radtek
10
Note, para Python 3 você tem prefixo com 0o (zero oh).
Mawg diz para restabelecer Monica em
1
Eu uso 0o em python 2.7.10
Wyrmwood,
125

Então, para pessoas que desejam uma semântica semelhante a:

$ chmod 755 somefile

Usar:

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

Se seu Python for anterior a 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
Dima
fonte
12
O formato python3 também funciona no python 2.7.9. Não verifiquei as versões anteriores.
Fred Mitchell,
3
A sintaxe do Python 3 retorna ao Python 2.6 docs.python.org/3/whatsnew/…
Pete,
Trabalhe para mim tks!
LandiLeite
Provavelmente deveria ser 00755, apenas para deixar claro para onde vão os bits suid / sgid / sticky, no caso de algum desenvolvedor posterior aparecer e quiser fazer esse script antigo usar, por exemplo, sgid com, 2755mas não consegue descobrir por quê as permanentes estão completamente danificadas. ;)
dannysauer
10

à esquerda 0significa que esta é uma constante octal , não decimal. e você precisa de um octal para alterar o modo de arquivo.

as permissões são uma máscara de bits, por exemplo, rwxrwx---está 111111000em binário, e é muito fácil agrupar os bits por 3 para converter para o octal, do que calcular a representação decimal.

0644(octal) está 0.110.100.100em binário (adicionei pontos para facilitar a leitura) ou, como você pode calcular, 420em decimal.

lenik
fonte
5

Use símbolos de permissão em vez de números

Seu problema teria sido evitado se você tivesse usado os símbolos de permissão com nomes mais semanticamente em vez de números mágicos brutos, por exemplo, 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
)

Isso está documentado em https://docs.python.org/3/library/os.html#os.chmod e os nomes são iguais aos valores da API POSIX C documentados em man 2 stat.

Outra vantagem é a maior portabilidade conforme mencionado na documentação:

Nota: Embora o Windows suporte chmod(), você só pode definir o sinalizador de somente leitura do arquivo com ele (por meio das constantes stat.S_IWRITEe stat.S_IREADou um valor inteiro correspondente). Todos os outros bits são ignorados.

chmod +xé demonstrado em: Como você faz um simples "chmod + x" de dentro do python?

Testado no Ubuntu 16.04, Python 3.5.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
1
Essa é a maneira correta de lidar com o problema.
carthurs
Eu sei disso do jeito python, mas dificilmente poderia ser mais feio :)
Tomasz Swider
2

Se você deseja as permissões salvas na string, faça

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

Usar as máscaras de bits stat. * Parece-me a maneira mais portátil e explícita de fazer isso. Mas, por outro lado, muitas vezes me esqueço da melhor forma de lidar com isso. Então, aqui está um exemplo de mascarar as permissões de 'grupo' e 'outras' e deixar as permissões de 'proprietário' intocadas. Usar bitmasks e subtração é um padrão ú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
fonte