Kiedy używać os.name, sys.platform lub platform.system?

104

O ile wiem, Python ma 3 sposoby sprawdzenia, na jakim systemie operacyjnym działa:

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

Znajomość tych informacji jest często przydatna przy importach warunkowych lub przy korzystaniu z funkcji różniących się między platformami (np. W time.clock()systemie Windows i time.time()UNIX).

Moje pytanie brzmi: dlaczego 3 różne sposoby to zrobić? Kiedy należy stosować jeden sposób, a nie inny? Który sposób jest „najlepszy” (najbardziej przyszłościowy lub najmniej skłonny do przypadkowego wykluczenia konkretnego systemu, na którym Twój program może faktycznie działać)?

Wydaje się, że sys.platformjest bardziej szczegółowe niż os.nameumożliwienie odróżnienia win32od cygwin(w przeciwieństwie do sprawiedliwego nt) i linux2od darwin(w przeciwieństwie do sprawiedliwego posix). Ale jeśli tak jest, to co z różnicą między sys.platformi platform.system()?

Na przykład, co jest lepsze, to:

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

albo to? :

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

Na razie będę się trzymał sys.platform, więc to pytanie nie jest szczególnie pilne, ale byłbym bardzo wdzięczny za wyjaśnienia w tej sprawie.

ztangent
źródło
15
użyj sys.platform.startswith('linux')zamiast sys.platform == 'linux2'dla przyszłej kompatybilności
jfs

Odpowiedzi:

68

Zanurzyłem się trochę w kodzie źródłowym.

Dane wyjściowe sys.platformi os.namesą określane w czasie kompilacji. platform.system()określa typ systemu w czasie wykonywania.

  • sys.platform jest określony jako zdefiniowany przez kompilator podczas konfiguracji kompilacji.
  • os.nameSprawdza, czy moduły konkretnych pewien OS są dostępne (np posix, nt...)
  • platform.system()faktycznie działa unamei potencjalnie kilka innych funkcji do określenia typu systemu w czasie wykonywania.

Moja sugestia:

  • Służy os.namedo sprawdzania, czy jest to system zgodny z POSIX.
  • Użyj, sys.platformaby sprawdzić, czy jest to linux, cygwin, darwin, atheos itp.
  • Użyj, platform.system()jeśli nie wierzysz innym źródłom.
moooeeeep
źródło
2
Zrobiłem więcej badań i oto szczegółowa odpowiedź: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Istnieje cienka linia różnicy między platform.system()i sys.platformi, co ciekawe, w większości przypadków platform.system()degeneruje sięsys.platform

Oto, co Python2.7\Lib\Platform.py\systemmówi Źródło

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

Również zgodnie z dokumentacją

os.uname ()

Zwraca 5-krotną krotkę zawierającą informacje identyfikujące bieżący system operacyjny. Krotka zawiera 5 ciągów: (nazwa sys, nazwa węzła, wydanie, wersja, maszyna). Niektóre systemy skracają nazwę węzła do 8 znaków lub do wiodącego składnika; lepszym sposobem na uzyskanie nazwy hosta jest gniazdo.gethostname () lub nawet gniazdo.gethostbyaddr (gniazdo.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
źródło
11

Z sys.platformdokumentów :

  • os.name ma grubszą ziarnistość
  • os.uname() podaje informacje o wersji zależne od systemu
  • platformModuł zawiera szczegółowe kontrole tożsamości systemu

Często „najlepszym” przyszłościowym sposobem sprawdzenia, czy niektóre funkcje są dostępne, jest po prostu próba ich użycia i skorzystanie z rozwiązania awaryjnego, jeśli się nie powiedzie.

a co z różnicą między sys.platform a platform.system ()?

platform.system()zwraca wartość znormalizowaną, że może uzyskać z kilku źródeł: os.uname(), sys.platform, verpolecenia (w systemie Windows).

jfs
źródło
10

Zależy to od tego, czy wolisz zgłaszać wyjątki, czy próbować czegokolwiek na niesprawdzonym systemie i czy Twój kod jest tak wysoki lub tak niski, że może lub nie może działać na podobnym, nieprzetestowanym systemie (np. Niesprawdzony Mac - „posix” lub na wbudowane systemy ARM). Bardziej pythoniczne jest nie wyliczenie wszystkich znanych systemów, ale przetestowanie możliwych odpowiednich właściwości. (np. uważa się za ważny endianness systemu, ale nieważne właściwości wieloprocesowe).

  • os.name jest wystarczającą rozdzielczością do prawidłowego korzystania z osmodułu. Możliwe wartości to „posix”, „nt”, „os2”, „ce”, „java” lub „riscos” w Pythonie 2.7, podczas gdy od Pythona 3.4 używane są tylko „posix”, „nt” i „java”.

  • sys.platform to lepsza rozdzielczość. Zalecane jest użycie if sys.platform.startswith('linux')idiomu, ponieważ „linux2” oznacza jądro Linuksa w wersji 2.xx lub 3. Starsze jądra nigdy nie są używane. W Pythonie 3.3 wszystkie systemy Linux są prostymi linuxami.

Nie znam specyfiki systemów "Mac" i "Java" i dlatego nie mogę wykorzystać wyników bardzo dobrej metody platform.system () do rozgałęziania, ale wykorzystałbym zalety platformmodułu do komunikatów i logowania błędów.

hynekcer
źródło
os.nameDopuszczalne wartości powrotne 'posix', 'nt', 'java'według Pythonie 3 Dokumenty . Zobacz też: dokumentacja modułu platformy . Ja nie wierzę 'riscos'i 'os2"Możliwe są następujące wartości zwracane z os.name; mogą to być wartości zwracane zsys.platform . Python 3 sys.platformdokumentacja wydaje się nie być wyczerpująca.
afeique
1
@afeique: Zaktualizowałem moją odpowiedź na nowszy Python, ale w tamtym czasie było dobrze. Zobacz Python 3.3 - os.name (najnowsza wersja w tym czasie). Python 2.7 jest nadal obsługiwany, a możliwą wartością jest „riscos”.
hynekcer
Dzięki @hynekcer, doceniam twoją edycję dodania numerów wersji Pythona. Przepraszam, że nie zdawałem sobie sprawy, że zmieniło się to po Pythonie 3.3. Nie przejrzałem różnych wersji dokumentacji i przyjąłem ogólne założenie, że zachowanie Pythona 3 os.namejest spójne we wszystkich wersjach. Nie sprawdziłem również dwukrotnie dokumentacji 2.7 , ale teraz wiem, że masz rację.
afeique
3

Uważam, że moduł platformy jest prawdopodobnie preferowany dla nowego kodu. Inni istnieli wcześniej. Jest to ewolucja, a pozostałe pozostają kompatybilne wstecz.

Keith
źródło
7
Zastanawiam się, czy uda nam się poprosić programistów Pythona o potwierdzenie tego. Może nawet ten, kto opracował moduł platformy.
ztangent