ควรใช้ os.name, sys.platform หรือ platform.system เมื่อใด


106

เท่าที่ฉันรู้ Python มี 3 วิธีในการค้นหาว่าระบบปฏิบัติการใดกำลังทำงานอยู่:

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

การทราบข้อมูลนี้มักมีประโยชน์ในการนำเข้าแบบมีเงื่อนไขหรือการใช้ฟังก์ชันการทำงานที่แตกต่างกันระหว่างแพลตฟอร์มต่างๆ (เช่นtime.clock()บน Windows เทียบtime.time()กับ UNIX)

คำถามของฉันคือทำไมถึงทำสิ่งนี้ได้ 3 วิธี ควรใช้วิธีใดวิธีหนึ่งไม่ใช่วิธีอื่น วิธีใดเป็นวิธีที่ 'ดีที่สุด' (การพิสูจน์ในอนาคตส่วนใหญ่หรือโอกาสน้อยที่สุดที่จะยกเว้นระบบใดระบบหนึ่งซึ่งโปรแกรมของคุณสามารถทำงานได้โดยไม่ได้ตั้งใจ)

ดูเหมือนว่าsys.platformจะเฉพาะเจาะจงมากกว่าos.nameทำให้คุณสามารถแยกแยะwin32จากcygwin(ตรงข้ามกับ just nt) และlinux2จากdarwin(ตรงข้ามกับ justposix ) แต่ถ้าเป็นเช่นนั้นแล้วความแตกต่างระหว่าง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

คำตอบ:


69

เจาะลึกลงไปในซอร์สโค้ด

ผลลัพธ์ของsys.platformและos.nameถูกกำหนดในเวลาคอมไพล์ platform.system()กำหนดประเภทของระบบในขณะทำงาน

  • sys.platform ถูกระบุเป็นคอมไพลเลอร์กำหนดระหว่างการกำหนดคอนฟิกบิลด์
  • os.nameตรวจสอบไม่ว่าจะเป็นโมดูลเฉพาะบางระบบปฏิบัติการที่มีอยู่ (เช่นposix, nt, ... )
  • platform.system()ทำงานจริงunameและอาจมีฟังก์ชันอื่น ๆ อีกมากมายเพื่อกำหนดประเภทของระบบในขณะทำงาน

คำแนะนำของฉัน:

  • ใช้ os.nameเพื่อตรวจสอบว่าเป็นระบบที่รองรับ posix หรือไม่
  • ใช้sys.platformตรวจสอบว่าเป็น linux, cygwin, darwin, atheos ฯลฯ หรือไม่
  • ใช้platform.system()หากคุณไม่เชื่อแหล่งข้อมูลอื่น

2
ฉันได้วิจัยมากขึ้นและนี่คือคำตอบรายละเอียด: stackoverflow.com/a/58071295/207661
Shital Shah

21

มีความแตกต่างของเส้นบาง ๆ ระหว่าง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) ระบบบางระบบตัดชื่อ nodename ให้เหลือ 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 แบบฝัง) pythonic เพิ่มเติมคือการไม่ระบุระบบที่รู้จักทั้งหมด แต่เพื่อทดสอบคุณสมบัติที่เกี่ยวข้องที่เป็นไปได้ (เช่นถือว่ามีความสำคัญเป็นจุดสิ้นสุดของระบบ แต่คุณสมบัติการประมวลผลหลายกระบวนการที่ไม่สำคัญ)

  • os.name เป็นความละเอียดที่เพียงพอสำหรับการใช้งานosโมดูลที่ถูกต้อง ค่าที่เป็นไปได้คือ 'posix', 'nt', 'os2', 'ce', 'java' หรือ 'riscos' ใน Python 2.7 ในขณะที่ใช้เฉพาะ 'posix', 'nt' และ 'java' ตั้งแต่ Python 3.4

  • 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'ตามหลาม 3 เอกสาร ดูเพิ่มเติม: เอกสารโมดูลแพลตฟอร์ม ฉันไม่เชื่อ'riscos'และ'os2'เป็นไปได้ที่จะคืนค่าจากos.name; พวกเขาอาจจะค่ากลับมาจาก sys.platformหลาม 3 sys.platformเอกสารไม่ปรากฏว่าจะหมดแรง
afeique

1
@afeique: ฉันอัปเดตคำตอบสำหรับ Python ที่ใหม่กว่า แต่ตอนนั้นถูกต้อง ดูPython 3.3 - os.name (เวอร์ชันล่าสุดในขณะนั้น) Python 2.7 ยังคงรองรับและ 'riscos' เป็นค่าที่เป็นไปได้สำหรับมัน
hynekcer

ขอบคุณ @hynekcer ขอขอบคุณที่แก้ไขเพื่อเพิ่มหมายเลขเวอร์ชัน Python ฉันขออภัยที่ไม่ทราบว่ามีการเปลี่ยนแปลงหลังจาก Python 3.3 ฉันไม่ได้อ่านเอกสารประกอบเวอร์ชันต่างๆและตั้งข้อสันนิษฐานเบื้องต้นว่าพฤติกรรมของ Python 3 os.nameมีความสอดคล้องกันในทุกเวอร์ชัน ฉันยังไม่ได้ตรวจสอบเอกสาร 2.7อีกครั้ง แต่ตอนนี้ฉันรู้แล้วว่าคุณถูกต้องแล้ว
afeique

3

ฉันเชื่อว่าโมดูลแพลตฟอร์มน่าจะเป็นที่ต้องการสำหรับโค้ดใหม่ คนอื่น ๆ มีอยู่ก่อนหน้านั้น มันเป็นวิวัฒนาการและอื่น ๆ ยังคงอยู่เพื่อความเข้ากันได้ย้อนหลัง


7
ฉันสงสัยว่าเราจะให้นักพัฒนา Python ยืนยันสิ่งนี้ได้หรือไม่ บางทีแม้แต่ใครก็ตามที่พัฒนาโมดูลแพลตฟอร์ม
ztangent
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.