Коли використовувати os.name, sys.platform або platform.system?


102

Наскільки я знаю, у Python є 3 способи з'ясувати, на якій операційній системі працює:

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

Знання цієї інформації часто корисне при умовному імпорті або використанні функціональних можливостей, що відрізняються між платформами (наприклад, time.clock()для Windows проти time.time()UNIX).

Моє запитання: чому 3 різні способи зробити це? Коли слід використовувати один, а не інший спосіб? Який спосіб є "найкращим" (найбільш стійкий до майбутнього або найменш ймовірний випадковий випадок конкретної системи, на якій може працювати ваша програма)?

Схоже , що sys.platformбільш специфічно , ніж os.name, що дозволяє відрізнити win32від cygwin(а не тільки nt), і linux2з darwin(а не тільки posix). Але якщо це так, що робити різницю між sys.platformі platform.system()?

Наприклад, що краще, це:

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

чи це? :

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

Зараз я буду дотримуватися цього sys.platform, тому це питання не є особливо актуальним, але я був би дуже вдячний за певні роз'яснення з цього приводу.


15
використовувати sys.platform.startswith('linux')замість sys.platform == 'linux2'майбутньої сумісності
jfs

Відповіді:


67

Трохи занурився у вихідний код.

Вихід sys.platformта os.nameвизначаються під час компіляції. platform.system()визначає тип системи під час виконання.

  • sys.platform задається як визначення компілятора під час конфігурації збірки.
  • os.nameперевіряє , буде чи конкретні модулі певних бе доступні (наприклад posix, nt...)
  • platform.system()насправді працює unameі, можливо, кілька інших функцій для визначення типу системи під час виконання.

Моя пропозиція:

  • Використовуйте, os.nameщоб перевірити, чи це система, сумісна з позиціями.
  • Використовуйте sys.platformдля перевірки, чи це Linux, cygwin, darwin, ateos тощо.
  • Використовуйте, platform.system()якщо не вірите іншим джерелам.

2
Я зробив більше досліджень, і ось детальна відповідь: stackoverflow.com/a/58071295/207661 .
Shital Shah

20

Існує різниця тонкій грані між platform.system()і sys.platformі цікаво для більшості випадків platform.system()вироджуютьсяsys.platform

Ось що Python2.7\Lib\Platform.py\systemговорить Джерело

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

Також згідно з документацією

os.uname ()

Поверніть 5-ти пакет, що містить інформацію, що ідентифікує поточну операційну систему. Кортеж містить 5 рядків: (sysname, nodename, release, version, machine). Деякі системи підрізають ім'я вузла до 8 символів або до провідного компонента; кращий спосіб отримати ім'я хоста - socket.gethostname () або навіть socket.gethostbyaddr (socket.gethostname ()).

Availability: recent flavors of Unix.

11

З sys.platformдокументів :

  • os.name має більш грубу зернистість
  • os.uname() надає інформацію про версію, що залежить від системи
  • platformМодуль містить докладні перевірки ідентичності системи

Найчастіше "найкращим" способом перевірити, чи є якась функціональність доступна, є лише спробувати використовувати її та використати резервну систему, якщо вона не працює.

як щодо різниці між sys.platform та platform.system ()?

platform.system()повертає нормалізоване значення , що він може отримати з кількох джерел: os.uname(), sys.platform, verкоманда (на Windows).


10

Це залежить від того, чи хочете ви підвищити виняток або спробувати що-небудь у неперевіреній системі та чи ваш код настільки високий або настільки низький, що він може чи не може працювати в подібній неперевіреній системі (наприклад, неперевірений Mac - 'posix' або на вбудовані системи ARM). Більш пітонічним є не перерахувати всі відомі системи, а перевірити можливі відповідні властивості. (наприклад, вважається важливою ефективність системи, але неважливими властивостями багатопроцесорної обробки.)

  • os.name - достатня роздільна здатність для правильного використання osмодуля. Можливі значення: 'posix', 'nt', 'os2', 'ce', 'java' або 'riscos' в Python 2.7, тоді як з Python 3.4 використовуються лише 'posix', 'nt' і 'java'.

  • sys.platform - тонка роздільна здатність. Рекомендується використовувати if sys.platform.startswith('linux')idiom, оскільки "linux2" означає ядро ​​Linux версії 2.xx або 3. Старіші ядра в даний час ніколи не використовуються. У Python 3.3 всі системи Linux є простими "linux".

Я не знаю специфіки систем "Mac" та "Java", тому я не можу використовувати результати дуже хорошого методу platform.system () для розгалуження, але я б використав переваги platformмодуля для повідомлень та журналу помилок.


os.nameМожливі повернені значення 'posix', 'nt', в 'java'відповідно до Python 3 Docs . Див. Також: документи модуля платформи . Я не вірю, 'riscos'і 'os2'можливі значення повернення від os.name; вони можуть бути поверненими значеннями відsys.platform . Python 3 sys.platformдокументація не представляється вичерпним.
afeique

1
@afeique: Я оновив свою відповідь щодо новішої версії Python, але на той момент це було правильно. Див. Python 3.3 - os.name (остання версія на той час). Python 2.7 все ще підтримується, і для нього можливим значенням є "ризик".
hynekcer

Дякую @hynekcer, я вдячний вашій редакції, щоб додати номери версій Python. Перепрошую, що не розумію, що це змінилося після Python 3.3. Я не ознайомився з різними версіями документації і зробив грубе припущення про те, що поведінка Python 3 os.nameбула послідовною у всіх версіях. Я також не переглядав документацію 2.7 , але тепер я знаю, що ви маєте рацію.
afeique

3

Я вважаю, що модуль платформи, мабуть, кращий для нового коду. Інші існували до цього. Це еволюція, а інші залишаються для зворотної сумісності.


7
Цікаво, чи можемо ми отримати будь-яких розробників Python для підтвердження цього. Можливо, навіть той, хто розробляв модуль платформи.
ztangent
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.