Wann sollte os.name, sys.platform oder platform.system verwendet werden?

102

Soweit ich weiß, hat Python drei Möglichkeiten, um herauszufinden, auf welchem ​​Betriebssystem es ausgeführt wird:

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

Die Kenntnis dieser Informationen ist häufig bei bedingten Importen oder bei der Verwendung von Funktionen hilfreich, die sich zwischen den Plattformen unterscheiden (z. B. time.clock()unter Windows und time.time()UNIX).

Meine Frage ist, warum 3 verschiedene Möglichkeiten, dies zu tun? Wann sollte ein Weg benutzt werden und nicht ein anderer? Welcher Weg ist der "beste" (am zukunftssichersten oder am wenigsten wahrscheinlich, um ein bestimmtes System, auf dem Ihr Programm tatsächlich ausgeführt werden kann, versehentlich auszuschließen)?

Es scheint sys.platformspezifischer zu sein als os.name, so dass Sie win32zwischen cygwin(im Gegensatz zu nur nt) und linux2von darwin(im Gegensatz zu nur posix) unterscheiden können. Aber wenn dem so ist, was ist dann mit dem Unterschied zwischen sys.platformund platform.system()?

Was zum Beispiel besser ist:

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

oder dieses? ::

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

Im Moment bleibe ich dabei sys.platform, daher ist diese Frage nicht besonders dringend, aber ich wäre sehr dankbar für eine Klarstellung in dieser Hinsicht.

ztangent
quelle
15
Verwenden Sie sys.platform.startswith('linux')anstelle von sys.platform == 'linux2'für zukünftige Kompatibilität
jfs

Antworten:

66

Tauchte ein bisschen in den Quellcode ein.

Die Ausgabe von sys.platformund os.namewird zur Kompilierungszeit bestimmt. platform.system()bestimmt den Systemtyp zur Laufzeit.

  • sys.platform wird während der Build-Konfiguration als Compiler-Definition angegeben.
  • os.nameüberprüft , ob bestimmte os spezifische Module zur Verfügung (zB posix, nt, ...)
  • platform.system()wird tatsächlich ausgeführt unameund möglicherweise mehrere andere Funktionen, um den Systemtyp zur Laufzeit zu bestimmen.

Mein Vorschlag:

  • Verwenden os.nameSie diese Option, um zu überprüfen, ob es sich um ein Posix-kompatibles System handelt.
  • Verwenden sys.platformSie diese Option, um zu überprüfen, ob es sich um Linux, Cygwin, Darwin, Atheos usw. handelt.
  • Verwenden platform.system()Sie, wenn Sie den anderen Quellen nicht glauben.
moooeeeep
quelle
2
Ich habe mehr recherchiert und hier ist die detaillierte Antwort: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Es gibt einen dünnen Linienunterschied zwischen platform.system()und sys.platformund interessanterweise platform.system()degeneriert in den meisten Fällen zusys.platform

Hier ist, was die Quelle Python2.7\Lib\Platform.py\systemsagt

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

Auch laut Dokumentation

os.uname ()

Geben Sie ein 5-Tupel mit Informationen zurück, die das aktuelle Betriebssystem identifizieren. Das Tupel enthält 5 Zeichenfolgen: (Systemname, Knotenname, Version, Version, Maschine). Einige Systeme kürzen den Knotennamen auf 8 Zeichen oder auf die führende Komponente. Ein besserer Weg, um den Hostnamen zu erhalten, ist socket.gethostname () oder sogar socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
quelle
11

Aus sys.platformDokumenten :

  • os.name hat eine gröbere Körnigkeit
  • os.uname() gibt systemabhängige Versionsinformationen
  • Das platformModul bietet detaillierte Überprüfungen der Systemidentität

Oft ist der "beste" zukunftssichere Weg, um zu testen, ob einige Funktionen verfügbar sind, nur zu versuchen, sie zu verwenden und einen Fallback zu verwenden, wenn sie fehlschlägt.

Was ist mit dem Unterschied zwischen sys.platform und platform.system ()?

platform.system()einen normalisierten Wert zurückgibt , dass es aus mehreren Quellen erhalten könnte: os.uname(), sys.platform, verBefehl (unter Windows).

jfs
quelle
10

Es hängt davon ab, ob Sie es vorziehen, eine Ausnahme auszulösen oder etwas auf einem nicht getesteten System zu versuchen, und ob Ihr Code so hoch oder so niedrig ist, dass er auf einem ähnlichen nicht getesteten System (z. B. ungetestetem Mac - 'posix' oder auf) funktionieren kann oder nicht eingebettete ARM-Systeme). Pythonischer ist es, nicht alle bekannten Systeme aufzulisten, sondern mögliche relevante Eigenschaften zu testen. (zB wird die Endianität des Systems als wichtig angesehen, aber unwichtige Mehrfachverarbeitungseigenschaften.)

  • os.name ist eine ausreichende Auflösung für die korrekte Verwendung des osModuls. Mögliche Werte sind 'posix', 'nt', 'os2', 'ce', 'java' oder 'riscos' in Python 2.7, während seit Python 3.4 nur 'posix', 'nt' und 'java' verwendet werden.

  • sys.platform ist eine feinere Auflösung. Es wird empfohlen, if sys.platform.startswith('linux')idiom zu verwenden, da "linux2" einen Linux-Kernel der Version 2.xx oder 3 bedeutet. Ältere Kernel werden derzeit nie verwendet. In Python 3.3 sind alle Linux-Systeme einfach 'Linux'.

Ich kenne die Besonderheiten von "Mac" - und "Java" -Systemen nicht und kann daher die Ergebnisse der sehr guten Methode platform.system () nicht zum Verzweigen verwenden, aber ich würde die Vorteile des platformModuls für Nachrichten und Fehlerprotokollierung nutzen.

Hynekcer
quelle
os.namemögliche Rückgabewerte sind 'posix', 'nt', 'java'nach Python 3 - Dokumenten . Siehe auch: Plattformmodul-Dokumente . Ich nicht glauben , 'riscos'und 'os2"sind mögliche Rückgabewerte aus os.name; Sie können Rückgabewerte von seinsys.platform . Die Python 3- sys.platformDokumentation scheint nicht vollständig zu sein.
Afeique
1
@afeique: Ich habe meine Antwort für neueres Python aktualisiert, aber es war zu diesem Zeitpunkt richtig. Siehe Python 3.3 - os.name (die aktuellste Version zu diesem Zeitpunkt). Python 2.7 wird weiterhin unterstützt und 'riscos' ist ein möglicher Wert dafür.
Hynekcer
Vielen Dank an @hynekcer. Ich freue mich über Ihre Bearbeitung, um Python-Versionsnummern hinzuzufügen. Ich entschuldige mich dafür, dass ich nicht bemerkt habe, dass es sich nach Python 3.3 geändert hat. Ich habe die verschiedenen Versionen der Dokumentation nicht durchgesehen und bin grob davon ausgegangen, dass das Python 3-Verhalten von os.nameVersion zu Version konsistent ist. Ich habe auch die 2.7-Dokumentation nicht noch einmal überprüft , aber ich weiß jetzt, dass Sie korrekt sind.
Afeique
3

Ich glaube, das Plattformmodul wird wahrscheinlich für neuen Code bevorzugt. Die anderen existierten davor. Es ist eine Evolution, und die anderen bleiben aus Gründen der Abwärtskompatibilität.

Keith
quelle
7
Ich frage mich, ob wir Python-Entwickler dazu bringen können, dies zu bestätigen. Vielleicht sogar wer auch immer das Plattformmodul entwickelt hat.
Ztangent