¿Cuándo usar os.name, sys.platform o platform.system?

102

Hasta donde yo sé, Python tiene 3 formas de averiguar en qué sistema operativo se está ejecutando:

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

Conocer esta información suele ser útil en importaciones condicionales o en el uso de funciones que difieren entre plataformas (por ejemplo, time.clock()en Windows frente a time.time()en UNIX).

Mi pregunta es, ¿por qué 3 formas diferentes de hacer esto? ¿Cuándo se debe utilizar una forma y no otra? ¿Cuál es la "mejor" (la más preparada para el futuro o la que es menos probable que excluya accidentalmente un sistema en particular en el que su programa puede ejecutarse)?

Parece que sys.platformes más específico que os.name, lo que le permite distinguir win32de cygwin(en oposición a solo nt) y linux2de darwin(en oposición a solo posix). Pero si es así, ¿qué pasa con la diferencia entre sys.platformy platform.system()?

Por ejemplo, cuál es mejor, esto:

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

¿o esto? :

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

Por ahora me atendré sys.platform, por lo que esta pregunta no es particularmente urgente, pero estaría muy agradecido por alguna aclaración al respecto.

ztangent
fuente
15
usar en sys.platform.startswith('linux')lugar de sys.platform == 'linux2'para compatibilidad futura
jfs

Respuestas:

67

Buceé un poco en el código fuente.

La salida de sys.platformy os.namese determina en tiempo de compilación. platform.system()determina el tipo de sistema en tiempo de ejecución.

  • sys.platform se especifica como una definición del compilador durante la configuración de compilación.
  • os.namecheques si los módulos específicos de ciertos OS están disponibles (por ejemplo posix, nt, ...)
  • platform.system()realmente se ejecuta unamey potencialmente varias otras funciones para determinar el tipo de sistema en tiempo de ejecución.

Mi sugerencia:

  • Úselo os.namepara verificar si es un sistema compatible con posix.
  • Úselo sys.platformpara verificar si es linux, cygwin, darwin, atheos, etc.
  • Úselo platform.system()si no cree en las otras fuentes.
moooeeeep
fuente
2
Investigué más y aquí está la respuesta detallada: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Hay una delgada diferencia entre platform.system()y, sys.platformy curiosamente para la mayoría de los casos platform.system()degenerasys.platform

Esto es lo que Python2.7\Lib\Platform.py\systemdice la Fuente

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 = ''

También según la documentación

os.uname ()

Devuelve una tupla de 5 que contiene información que identifica el sistema operativo actual. La tupla contiene 5 cadenas: (sysname, nodename, release, version, machine). Algunos sistemas truncan el nombre de nodo a 8 caracteres o al componente principal; una mejor manera de obtener el nombre de host es socket.gethostname () o incluso socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
fuente
11

De los sys.platformdocumentos :

  • os.name tiene una granularidad más gruesa
  • os.uname() proporciona información de versión dependiente del sistema
  • El platformmódulo proporciona comprobaciones detalladas de la identidad del sistema.

A menudo, la "mejor" forma a prueba de futuro de probar si alguna funcionalidad está disponible es simplemente intentar usarla y usar una alternativa si falla.

¿Qué pasa con la diferencia entre sys.platform y platform.system ()?

platform.system()devuelve un valor normalizado que podría obtener de varias fuentes: os.uname(), sys.platform, vercomandos (en Windows).

jfs
fuente
10

Depende de si prefiere generar una excepción o probar algo en un sistema no probado y si su código es de un nivel tan alto o tan bajo que puede o no puede funcionar en un sistema similar no probado (por ejemplo, Mac no probado - 'posix' o en sistemas ARM integrados). Más pitónico es no enumerar todos los sistemas conocidos, sino probar posibles propiedades relevantes. (Por ejemplo, se considera importante la endiabilidad del sistema, pero propiedades de multiprocesamiento sin importancia).

  • os.name es una resolución suficiente para el uso correcto del osmódulo. Los valores posibles son 'posix', 'nt', 'os2', 'ce', 'java' o 'riscos' en Python 2.7, mientras que solo se usan 'posix', 'nt' y 'java' desde Python 3.4.

  • sys.platform tiene una resolución más fina. Se recomienda usar if sys.platform.startswith('linux')modismo porque "linux2" significa una versión de kernel de Linux 2.xx o 3. Actualmente, los kernels más antiguos nunca se usan. En Python 3.3, todos los sistemas Linux son simples 'linux'.

No conozco los detalles de los sistemas "Mac" y "Java", por lo que no puedo usar los resultados del muy buen método platform.system () para ramificar, pero usaría las ventajas del platformmódulo para mensajes y registro de errores.

Hynekcer
fuente
os.nameposibles valores de retorno son 'posix', 'nt', 'java'de acuerdo con Python 3 docs . Consulte también: documentos del módulo de plataforma . Yo no creo 'riscos'y 'os2'son posibles valores de retorno de os.name; pueden ser valores de retorno desys.platform . La documentación de Python 3sys.platform no parece ser exhaustiva.
afeique
1
@afeique: Actualicé mi respuesta para Python más nuevo, pero era correcto en ese momento. Consulte Python 3.3 - os.name (la última versión en ese momento). Python 2.7 todavía es compatible y 'riscos' es un valor posible para él.
hynekcer
Gracias @hynekcer, agradezco su edición para agregar números de versión de Python. Pido disculpas por no darme cuenta de que cambió después de Python 3.3. No examiné las diferentes versiones de la documentación y asumí que el comportamiento de Python 3 os.nameera consistente en todas las versiones. Tampoco verifiqué la documentación 2.7 , pero ahora sé que estás en lo correcto.
afeique
3

Creo que el módulo de plataforma probablemente sea el preferido para el nuevo código. Los otros existieron antes que él. Es una evolución, y los demás permanecen por compatibilidad con versiones anteriores.

Keith
fuente
7
Me pregunto si podemos conseguir que algún desarrollador de Python confirme esto. Quizás incluso quien desarrolló el módulo de plataforma.
ztangent