Quando usar os.name, sys.platform ou platform.system?

102

Pelo que eu sei, o Python tem três maneiras de descobrir em que sistema operacional está sendo executado:

  1. os.name
  2. sys.platform
  3. platform.system()

Conhecer essas informações geralmente é útil em importações condicionais ou no uso de funcionalidades que diferem entre as plataformas (por exemplo, time.clock()no Windows x time.time()UNIX).

Minha pergunta é: por que três maneiras diferentes de fazer isso? Quando uma maneira deve ser usada e não outra? Qual maneira é a 'melhor' (mais preparada para o futuro ou menos provável de excluir acidentalmente um sistema específico no qual seu programa pode realmente ser executado)?

Parece que sys.platformé mais específico do que os.name, permitindo a você distinguir win32de cygwin(em oposição a apenas nt) e linux2de darwin(em oposição a apenas posix). Mas se for assim, que tal a diferença entre sys.platforme platform.system()?

Por exemplo, o que é melhor, este:

import sys
if sys.platform == 'linux2':
    # Do Linux-specific stuff

ou isto? :

import platform
if platform.system() == 'Linux':
    # Do Linux-specific stuff

Por enquanto, irei me limitar a sys.platform, então esta questão não é particularmente urgente, mas eu ficaria muito grato por alguns esclarecimentos a respeito disso.

ztangent
fonte
15
use em sys.platform.startswith('linux')vez de sys.platform == 'linux2'para compatibilidade futura
jfs

Respostas:

67

Mergulhei um pouco no código-fonte.

A saída de sys.platforme os.nameé determinada em tempo de compilação. platform.system()determina o tipo de sistema em tempo de execução.

  • sys.platform é especificado como um compilador definido durante a configuração de construção.
  • os.nameverifica se módulos específicos certa OS estão disponíveis (por exemplo posix, nt...)
  • platform.system()realmente executa unamee potencialmente várias outras funções para determinar o tipo de sistema em tempo de execução.

Minha sugestão:

  • Use os.namepara verificar se é um sistema compatível com posix.
  • Use sys.platformpara verificar se é um linux, cygwin, darwin, atheos, etc.
  • Use platform.system()se você não acreditar nas outras fontes.
moooeeeep
fonte
2
Fiz mais pesquisas e aqui está a resposta detalhada: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Há uma diferença de linha tênue entre platform.system()e sys.platforme, curiosamente, para a maioria dos casos platform.system()degenera parasys.platform

Aqui está o que a fonte Python2.7\Lib\Platform.py\systemdiz

def system():

    """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.

        An empty string is returned if the value cannot be determined.

    """
    return uname()[0]

def uname():
    # Get some infos from the builtin os.uname API...
    try:
        system,node,release,version,machine = os.uname()
    except AttributeError:
        no_os_uname = 1

    if no_os_uname or not filter(None, (system, node, release, version, machine)):
        # Hmm, no there is either no uname or uname has returned
        #'unknowns'... we'll have to poke around the system then.
        if no_os_uname:
            system = sys.platform
            release = ''
            version = ''
            node = _node()
            machine = ''

Também pela documentação

os.uname ()

Retorne uma tupla de 5 contendo informações que identificam o sistema operacional atual. A tupla contém 5 strings: (sysname, nodename, release, version, machine). Alguns sistemas truncam o nome do nó em 8 caracteres ou no componente inicial; a melhor maneira de obter o nome do host é socket.gethostname () ou mesmo socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
fonte
11

Dos sys.platformdocumentos :

  • os.name tem uma granularidade mais grosseira
  • os.uname() fornece informações de versão dependentes do sistema
  • O platformmódulo fornece verificações detalhadas para a identidade do sistema

Freqüentemente, a "melhor" maneira preparada para o futuro de testar se alguma funcionalidade está disponível é apenas tentar usá-la e usar um fallback se ela falhar.

e quanto à diferença entre sys.platform e platform.system ()?

platform.system()retorna um valor normalizado que pode começar a partir de várias fontes: os.uname(), sys.platform, vercomando (no Windows).

jfs
fonte
10

Depende se você prefere gerar exceção ou tentar qualquer coisa em um sistema não testado e se seu código é de nível tão alto ou baixo que pode ou não funcionar em um sistema não testado semelhante (por exemplo, Mac não testado - 'posix' ou em sistemas ARM incorporados). Mais pitônico é não enumerar todos os sistemas conhecidos, mas testar possíveis propriedades relevantes. (por exemplo, é considerado importante o endianess do sistema, mas propriedades de multiprocessamento sem importância.)

  • os.name é uma resolução suficiente para o uso correto do osmódulo. Os valores possíveis são 'posix', 'nt', 'os2', 'ce', 'java' ou 'riscos' em Python 2.7, enquanto apenas 'posix', 'nt' e 'java' são usados ​​desde Python 3.4.

  • sys.platform é uma resolução mais precisa. É recomendado usar o if sys.platform.startswith('linux')idioma porque "linux2" significa um kernel Linux versão 2.xx ou 3. Kernels mais antigos nunca são usados. No Python 3.3, todos os sistemas Linux são simples 'linux'.

Não conheço as especificações dos sistemas "Mac" e "Java" e, portanto, não posso usar os resultados de um método muito bom platform.system () para ramificação, mas usaria as vantagens do platformmódulo para mensagens e registro de erros.

Hynekcer
fonte
os.namepossíveis valores de retorno são 'posix', 'nt', 'java'de acordo com o Python 3 docs . Veja também: documentação do módulo da plataforma . Eu não acredito 'riscos'e 'os2'são possíveis valores de retorno de os.name; eles podem ser valores de retorno desys.platform . A documentação do Python 3sys.platform não parece ser exaustiva.
afeique
1
@afeique: Eu atualizei minha resposta para o Python mais recente, mas estava certo na época. Consulte Python 3.3 - os.name (a versão mais recente na época). Python 2.7 ainda é compatível e 'riscos' é um valor possível para ele.
hynekcer
Obrigado @hynekcer, agradeço sua edição para adicionar números de versão do Python. Peço desculpas por não perceber que isso mudou depois do Python 3.3. Não examinei as diferentes versões da documentação e fiz a suposição grosseira de que o comportamento do Python 3 os.nameera consistente em todas as versões. Também não verifiquei novamente a documentação do 2.7 , mas agora sei que você está correto.
afeique
3

Acredito que o módulo da plataforma seja provavelmente o preferido para o novo código. Os outros existiram antes disso. É uma evolução, e as outras permanecem para compatibilidade com versões anteriores.

Keith
fonte
7
Gostaria de saber se podemos fazer com que algum desenvolvedor Python confirme isso. Quem sabe até quem desenvolveu o módulo da plataforma.
ztangent