Kapan menggunakan os.name, sys.platform, atau platform.system?

102

Sejauh yang saya tahu, Python memiliki 3 cara untuk mengetahui sistem operasi apa yang sedang berjalan:

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

Mengetahui informasi ini sering kali berguna dalam impor bersyarat, atau menggunakan fungsionalitas yang berbeda antar platform (misalnya time.clock()di Windows vs time.time()di UNIX).

Pertanyaan saya adalah, mengapa 3 cara berbeda untuk melakukan ini? Kapan satu cara harus digunakan dan bukan yang lain? Cara manakah yang 'terbaik' (paling tahan masa depan atau paling tidak mungkin secara tidak sengaja mengecualikan sistem tertentu tempat program Anda sebenarnya dapat berjalan)?

Sepertinya sys.platformlebih spesifik daripada os.name, memungkinkan Anda untuk membedakan win32dari cygwin(sebagai lawan dari hanya nt), dan linux2dari darwin(sebagai lawan dari hanya posix). Tetapi jika demikian, bagaimana dengan perbedaan antara sys.platformdan platform.system()?

Misalnya, mana yang lebih baik, ini:

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

atau ini? :

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

Untuk saat ini saya akan bertahan sys.platform, jadi pertanyaan ini tidak terlalu mendesak, tetapi saya akan sangat berterima kasih atas beberapa klarifikasi mengenai hal ini.

ztangent
sumber
15
gunakan sys.platform.startswith('linux')alih-alih sys.platform == 'linux2'untuk kompatibilitas di masa mendatang
jfs

Jawaban:

67

Menyelam sedikit ke dalam kode sumber.

Keluaran dari sys.platformdan os.nameditentukan pada waktu kompilasi. platform.system()menentukan jenis sistem pada waktu proses.

  • sys.platform ditetapkan sebagai yang ditentukan kompiler selama konfigurasi build.
  • os.namememeriksa apakah modul khusus os tertentu yang tersedia (misalnya posix, nt, ...)
  • platform.system()benar-benar berjalan unamedan berpotensi beberapa fungsi lain untuk menentukan jenis sistem pada waktu proses.

Saran saya:

  • Gunakan os.nameuntuk memeriksa apakah itu sistem yang sesuai dengan posix.
  • Gunakan sys.platformuntuk memeriksa apakah itu linux, cygwin, darwin, atheos, dll.
  • Gunakan platform.system()jika Anda tidak mempercayai sumber lain.
moooeeeep
sumber
2
Saya melakukan lebih banyak penelitian dan inilah jawaban terperinci: stackoverflow.com/a/58071295/207661 .
Shital Shah
20

Ada perbedaan garis tipis antara platform.system()dan sys.platformdan yang menarik untuk kebanyakan kasus platform.system()merosot menjadisys.platform

Berikut adalah apa Sumber Python2.7\Lib\Platform.py\systemmengatakan

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

Juga sesuai dokumentasi

os.uname ()

Kembalikan 5-tupel yang berisi informasi yang mengidentifikasi sistem operasi saat ini. Tuple berisi 5 string: (sysname, nodename, release, version, machine). Beberapa sistem memotong nama nodename menjadi 8 karakter atau menjadi komponen utama; cara yang lebih baik untuk mendapatkan nama host adalah socket.gethostname () atau bahkan socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.
Abhijit
sumber
11

Dari sys.platformdokumen :

  • os.name memiliki perincian yang lebih kasar
  • os.uname() memberikan informasi versi yang bergantung pada sistem
  • The platformmodul menyediakan pemeriksaan rinci untuk identitas sistem

Seringkali cara yang "terbaik" untuk masa depan untuk menguji apakah beberapa fungsionalitas tersedia hanya dengan mencoba menggunakannya dan menggunakan fallback jika gagal.

bagaimana dengan perbedaan antara sys.platform dan platform.system ()?

platform.system()mengembalikan nilai normalisasi yang mungkin mendapatkan dari beberapa sumber: os.uname(), sys.platform, verperintah (pada Windows).

jfs
sumber
10

Itu tergantung pada apakah Anda lebih suka memunculkan pengecualian atau mencoba sesuatu pada sistem yang belum diuji dan apakah kode Anda sangat tinggi atau sangat rendah sehingga dapat atau tidak dapat bekerja pada sistem serupa yang belum diuji (misalnya Mac yang belum diuji - 'posix' atau pada sistem ARM tertanam). Lebih pythonic adalah tidak menghitung semua sistem yang dikenal tetapi untuk menguji kemungkinan properti yang relevan. (misalnya dianggap penting sebagai endianess dari sistem tetapi properti multiprosesing tidak penting.)

  • os.name adalah resolusi yang cukup untuk penggunaan osmodul yang benar. Nilai yang memungkinkan adalah 'posix', 'nt', 'os2', 'ce', 'java' atau 'riscos' dengan Python 2.7, sementara hanya 'posix', 'nt' dan 'java' yang digunakan sejak Python 3.4.

  • sys.platform adalah resolusi yang lebih baik. Disarankan untuk menggunakan if sys.platform.startswith('linux')idiom karena "linux2" berarti kernel Linux versi 2.xx atau 3. Kernel yang lebih lama saat ini tidak pernah digunakan. Dalam Python 3.3 adalah semua sistem Linux sederhana 'linux'.

Saya tidak tahu secara spesifik dari sistem "Mac" dan "Java" sehingga saya tidak dapat menggunakan hasil dari metode platform.system () yang sangat bagus untuk percabangan, tetapi saya akan menggunakan kelebihan platformmodul untuk pesan dan error logging.

hynekcer
sumber
os.namemungkin kembali nilai-nilai yang 'posix', 'nt', 'java'menurut Python 3 docs . Lihat juga: dokumen modul platform . Saya tidak percaya 'riscos'dan 'os2'adalah kemungkinan nilai kembali dari os.name; mereka mungkin mengembalikan nilai darisys.platform . The Python 3 sys.platformdokumentasi tidak muncul untuk menjadi lengkap.
afeique
1
@afeique: Saya memperbarui jawaban saya untuk Python yang lebih baru, tetapi jawaban itu benar pada saat itu. Lihat Python 3.3 - os.name (versi terbaru saat itu). Python 2.7 masih didukung dan 'riscos' adalah nilai yang memungkinkan.
hynekcer
Terima kasih @hynekcer, saya menghargai hasil edit Anda untuk menambahkan nomor versi Python. Saya minta maaf karena tidak menyadarinya berubah setelah Python 3.3. Saya tidak membaca dengan teliti berbagai versi dokumentasi dan membuat asumsi kasar bahwa perilaku Python 3 os.namekonsisten di semua versi. Saya juga tidak memeriksa ulang dokumentasi 2.7 , tapi sekarang saya tahu Anda benar.
afeique
3

Saya yakin modul platform mungkin lebih disukai untuk kode baru. Yang lainnya sudah ada sebelumnya. Ini adalah evolusi, dan yang lainnya tetap untuk kompatibilitas ke belakang.

Keith
sumber
7
Saya ingin tahu apakah kita bisa meminta pengembang Python untuk mengonfirmasi ini. Mungkin bahkan siapa pun yang mengembangkan modul platform.
ztangent