Quando utilizzare os.name, sys.platform o platform.system?


102

Per quanto ne so, Python ha 3 modi per scoprire su quale sistema operativo è in esecuzione:

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

La conoscenza di queste informazioni è spesso utile nelle importazioni condizionali o nell'utilizzo di funzionalità che differiscono tra le piattaforme (ad esempio time.clock()su Windows rispetto time.time()a UNIX).

La mia domanda è: perché 3 modi diversi per farlo? Quando dovrebbe essere usato un modo e non un altro? Qual è il modo "migliore" (più a prova di futuro o meno probabile che escluda accidentalmente un particolare sistema su cui il tuo programma può effettivamente essere eseguito)?

Sembra che sys.platformsia più specifico di os.name, permettendoti di distinguere win32da cygwin(al contrario di just nt) e linux2da darwin(al contrario di just posix). Ma se è così, che dire della differenza tra sys.platforme platform.system()?

Ad esempio, che è meglio, questo:

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

o questo? :

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

Per ora mi atterrò sys.platform, quindi questa domanda non è particolarmente urgente, ma sarei molto grato per alcuni chiarimenti in merito.


15
utilizzare sys.platform.startswith('linux')invece di sys.platform == 'linux2'per compatibilità futura
jfs

Risposte:


67

Mi sono tuffato un po 'nel codice sorgente.

L'output di sys.platforme os.nameviene determinato in fase di compilazione. platform.system()determina il tipo di sistema in fase di esecuzione.

  • sys.platform è specificato come un compilatore definito durante la configurazione della build.
  • os.namecontrolla se moduli specifici certa os sono disponibili (ad esempio posix, nt...)
  • platform.system()effettivamente viene eseguito unamee potenzialmente diverse altre funzioni per determinare il tipo di sistema in fase di esecuzione.

Il mio consiglio:

  • Da utilizzare os.nameper verificare se si tratta di un sistema conforme a posix.
  • Da utilizzare sys.platformper verificare se si tratta di Linux, Cygwin, Darwin, Atheos, ecc.
  • Usalo platform.system()se non credi alle altre fonti.

2
Ho fatto più ricerche ed ecco la risposta dettagliata: stackoverflow.com/a/58071295/207661 .
Shital Shah

20

C'è una sottile differenza tra platform.system()e sys.platforme, cosa interessante, nella maggior parte dei casi platform.system()degenera insys.platform

Ecco cosa Python2.7\Lib\Platform.py\systemdice la Fonte

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

Anche per la documentazione

os.uname ()

Restituisce una tupla di 5 elementi contenente informazioni che identificano il sistema operativo corrente. La tupla contiene 5 stringhe: (sysname, nodename, release, version, machine). Alcuni sistemi troncano il nome nodo a 8 caratteri o al componente iniziale; un modo migliore per ottenere il nome host è socket.gethostname () o anche socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.

11

Dai sys.platformdocumenti :

  • os.name ha una granulosità più grossolana
  • os.uname() fornisce informazioni sulla versione dipendenti dal sistema
  • Il platformmodulo fornisce controlli dettagliati per l'identità del sistema

Spesso il modo "migliore" a prova di futuro per verificare se alcune funzionalità sono disponibili è solo provare a usarle e utilizzare un fallback se fallisce.

che dire della differenza tra sys.platform e platform.system ()?

platform.system()restituisce un valore normalizzato che si potrebbe ottenere da diverse fonti: os.uname(), sys.platform, verdi comando (su Windows).


10

Dipende dal fatto che si preferisca sollevare un'eccezione o provare qualcosa su un sistema non testato e se il proprio codice è di livello così alto o così basso che può o non può funzionare su un sistema simile non testato (ad esempio Mac non testato - 'posix' o su sistemi ARM integrati). Più pitonico è non enumerare tutti i sistemi conosciuti ma testare possibili proprietà rilevanti. (ad esempio, è considerata importante l'endianità del sistema ma proprietà di multiprocessing non importanti.)

  • os.name è una risoluzione sufficiente per il corretto utilizzo del osmodulo. I valori possibili sono "posix", "nt", "os2", "ce", "java" o "riscos" in Python 2.7, mentre a partire da Python 3.4 vengono utilizzati solo "posix", "nt" e "java".

  • sys.platform è una risoluzione più fine. Si consiglia di utilizzare if sys.platform.startswith('linux')idioma perché "linux2" indica una versione del kernel Linux 2.xx o 3. Attualmente i kernel più vecchi non vengono mai utilizzati. In Python 3.3 tutti i sistemi Linux sono semplici "linux".

Non conosco le specifiche dei sistemi "Mac" e "Java" e quindi non posso utilizzare i risultati dell'ottimo metodo platform.system () per la ramificazione, ma utilizzerei i vantaggi del platformmodulo per i messaggi e la registrazione degli errori.


os.namepossibili valori di ritorno sono 'posix', 'nt', 'java'secondo Python 3 documenti . Vedi anche: documentazione del modulo della piattaforma . Io non credo 'riscos'e 'os2'sono possibili valori di ritorno da os.name; possono essere valori di ritorno dasys.platform . La documentazione di Python 3sys.platform non sembra essere esaustiva.
afeique

1
@afeique: ho aggiornato la mia risposta per il nuovo Python, ma era giusto in quel momento. Vedi Python 3.3 - os.name (l'ultima versione in quel momento). Python 2.7 è ancora supportato e "riscos" è un possibile valore per esso.
hynekcer

Grazie @hynekcer, apprezzo la tua modifica per aggiungere i numeri di versione di Python. Mi scuso per non essermi reso conto che è cambiato dopo Python 3.3. Non ho esaminato le diverse versioni della documentazione e ho ipotizzato che il comportamento di Python 3 os.namefosse coerente tra le versioni. Inoltre non ho ricontrollato la documentazione 2.7 , ma ora so che hai ragione.
afeique

3

Credo che il modulo della piattaforma sia probabilmente preferito per il nuovo codice. Gli altri esistevano prima. È un'evoluzione e gli altri rimangono per compatibilità all'indietro.


7
Mi chiedo se possiamo convincere gli sviluppatori Python a confermarlo. Forse anche chiunque abbia sviluppato il modulo della piattaforma.
ztangent
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.