Quand utiliser os.name, sys.platform ou platform.system?

105

Pour autant que je sache, Python a 3 façons de savoir sur quel système d'exploitation fonctionne:

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

Connaître ces informations est souvent utile dans les importations conditionnelles, ou en utilisant des fonctionnalités qui diffèrent entre les plates-formes (par exemple time.clock()sous Windows et time.time()sous UNIX).

Ma question est, pourquoi 3 façons différentes de faire cela? Quand faut-il utiliser un moyen et pas un autre? Quelle est la «meilleure» méthode (la plus à l'épreuve du temps ou la moins susceptible d'exclure accidentellement un système particulier sur lequel votre programme peut réellement fonctionner)?

Il semble que ce sys.platformsoit plus spécifique que os.name, vous permettant de distinguer win32de cygwin(par opposition à juste nt) et linux2de darwin(par opposition à juste posix). Mais si tel est le cas, qu'en est-il de la différence entre sys.platformet platform.system()?

Par exemple, ce qui est mieux, ceci:

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

ou ca? :

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

Pour l'instant, je sys.platformm'en tiendrai, donc cette question n'est pas particulièrement urgente, mais je serais très reconnaissant d'avoir des éclaircissements à ce sujet.

ztangent
la source
15
utiliser sys.platform.startswith('linux')au lieu de sys.platform == 'linux2'pour une compatibilité future
jfs

Réponses:

68

Plongé un peu dans le code source.

La sortie de sys.platformet os.nameest déterminée au moment de la compilation. platform.system()détermine le type de système au moment de l'exécution.

  • sys.platform est spécifié comme un compilateur défini lors de la configuration de construction.
  • os.namevérifie si certains modules spécifiques os sont disponibles (par exemple posix, nt...)
  • platform.system()exécute réellement unameet potentiellement plusieurs autres fonctions pour déterminer le type de système au moment de l'exécution.

Ma suggestion:

  • Utilisez os.namepour vérifier s'il s'agit d'un système compatible posix.
  • Utilisez sys.platformpour vérifier s'il s'agit d'un linux, cygwin, darwin, atheos, etc.
  • À utiliser platform.system()si vous ne croyez pas aux autres sources.
moooeeeep
la source
2
J'ai fait plus de recherches et voici la réponse détaillée: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Il y a une fine différence entre platform.system()et sys.platformet il est intéressant pour la plupart des cas de platform.system()dégénérer ensys.platform

Voici ce que Python2.7\Lib\Platform.py\systemdit la source

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

Également par la documentation

os.uname ()

Renvoie un 5-tuple contenant des informations identifiant le système d'exploitation actuel. Le tuple contient 5 chaînes: (sysname, nodename, release, version, machine). Certains systèmes tronquent le nom du nœud à 8 caractères ou au composant principal; une meilleure façon d'obtenir le nom d'hôte est socket.gethostname () ou même socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
la source
11

À partir de la sys.platformdocumentation :

  • os.name a une granularité plus grossière
  • os.uname() donne des informations de version dépendant du système
  • Le platformmodule fournit des contrôles détaillés de l'identité du système

Souvent, le «meilleur» moyen à l'épreuve du temps de tester si certaines fonctionnalités sont disponibles est simplement d'essayer de les utiliser et d'utiliser une solution de secours en cas d'échec.

qu'en est-il de la différence entre sys.platform et platform.system ()?

platform.system()retourne une valeur normalisée qu'il pourrait obtenir à partir de plusieurs sources: os.uname(), sys.platform, vercommande (sous Windows).

jfs
la source
10

Cela dépend si vous préférez déclencher une exception ou essayer quoi que ce soit sur un système non testé et si votre code est si haut ou si bas niveau qu'il peut ou ne peut pas fonctionner sur un système similaire non testé (par exemple Mac non testé - 'posix' ou sur systèmes ARM embarqués). Plus pythonique est de ne pas énumérer tous les systèmes connus mais de tester d'éventuelles propriétés pertinentes. (par exemple, il est considéré comme important la finalité du système mais les propriétés de multitraitement sans importance.)

  • os.name est une résolution suffisante pour une utilisation correcte du osmodule. Les valeurs possibles sont 'posix', 'nt', 'os2', 'ce', 'java' ou 'riscos' en Python 2.7, tandis que seuls les 'posix', 'nt' et 'java' sont utilisés depuis Python 3.4.

  • sys.platform est une résolution plus fine. Il est recommandé d'utiliser if sys.platform.startswith('linux')idiom car «linux2» signifie un noyau Linux version 2.xx ou 3. Les noyaux plus anciens ne sont actuellement jamais utilisés. Dans Python 3.3, tous les systèmes Linux sont de simples «linux».

Je ne connais pas les spécificités des systèmes "Mac" et "Java" et je ne peux donc pas utiliser les résultats de la très bonne méthode platform.system () pour le branchement, mais j'utiliserais les avantages du platformmodule pour les messages et la journalisation des erreurs.

hynekcer
la source
os.nameles valeurs possibles de retour sont 'posix', 'nt', 'java'selon python 3 documents . Voir aussi: documentation du module de plateforme . Je ne crois pas'riscos' et 'os2«sont des valeurs de retour possibles de os.name; il peut s'agir de valeurs de retour desys.platform . La documentation Python 3sys.platform ne semble pas exhaustive.
afeique
1
@afeique: J'ai mis à jour ma réponse pour Python plus récent, mais c'était juste à ce moment-là. Voir Python 3.3 - os.name (la dernière version à ce moment-là). Python 2.7 est toujours pris en charge et «riscos» en est une valeur possible.
hynekcer
Merci @hynekcer, j'apprécie votre modification pour ajouter les numéros de version de Python. Je m'excuse de ne pas me rendre compte qu'il a changé après Python 3.3. Je n'ai pas parcouru les différentes versions de la documentation et j'ai fait l'hypothèse grossière que le comportement de Python 3 os.nameétait cohérent entre les versions. Je n'ai pas non plus revérifié la documentation 2.7 , mais je sais maintenant que vous avez raison.
afeique
3

Je crois que le module de plate-forme est probablement préféré pour le nouveau code. Les autres existaient avant lui. C'est une évolution, et les autres restent pour compatibilité ascendante.

Keith
la source
7
Je me demande si nous pouvons obtenir des développeurs Python pour confirmer cela. Peut-être même celui qui a développé le module de plateforme.
ztangent