Python 的“platform.mac_ver()”报告不正确的 MacOS 版本

问题描述 投票:0回答:4

我正在使用 Python

platform
模块 来识别 MacOS 版本,如下所示:

import platform
print(platform.mac_ver())

输出:

In [1]: import platform

In [2]: platform.mac_ver()
Out[2]: ('10.16', ('', '', ''), 'x86_64')

我已经更新到BigSur,版本不正确,应该是11.0.1

enter image description here

我查看了平台的源代码,它似乎解析了这个文件

/System/Library/CoreServices/SystemVersion.plist
来获取信息。 当从 Python 读取此文件时,我得到的版本不正确,但从 bash 读取时,它是正确的版本

重击:

Amirs-MacBook-Pro:~ arossert$ cat /System/Library/CoreServices/SystemVersion.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>20B50</string>
    <key>ProductCopyright</key>
    <string>1983-2020 Apple Inc.</string>
    <key>ProductName</key>
    <string>macOS</string>
    <key>ProductUserVisibleVersion</key>
    <string>11.0.1</string>
    <key>ProductVersion</key>
    <string>11.0.1</string>
    <key>iOSSupportVersion</key>
    <string>14.2</string>
</dict>
</plist>

Python:

In [4]: print(open("/System/Library/CoreServices/SystemVersion.plist").read())
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>20B50</string>
    <key>ProductCopyright</key>
    <string>1983-2020 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.16</string>
    <key>ProductVersion</key>
    <string>10.16</string>
    <key>iOSSupportVersion</key>
    <string>14.2</string>
</dict>
</plist>

我错过了什么?

这是同一个

ipython
会话的输出

In [3]: print(open("/System/Library/CoreServices/SystemVersion.plist").read())
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>20B50</string>
    <key>ProductCopyright</key>
    <string>1983-2020 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.16</string>
    <key>ProductVersion</key>
    <string>10.16</string>
    <key>iOSSupportVersion</key>
    <string>14.2</string>
</dict>
</plist>


In [4]: cat /System/Library/CoreServices/SystemVersion.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>20B50</string>
    <key>ProductCopyright</key>
    <string>1983-2020 Apple Inc.</string>
    <key>ProductName</key>
    <string>macOS</string>
    <key>ProductUserVisibleVersion</key>
    <string>11.0.1</string>
    <key>ProductVersion</key>
    <string>11.0.1</string>
    <key>iOSSupportVersion</key>
    <string>14.2</string>
</dict>
</plist>
python macos
4个回答
12
投票

在 Big Sur 发行说明的已知问题部分中,存在以下内容:

由于 macOS 版本从 10.x 更改为 11,某些第三方脚本可能会产生意外结果。(62477208)

解决方法:在调用环境中设置 SYSTEM_VERSION_COMPAT=1,例如:$ SYSTEM_VERSION_COMPAT=1 Legacy_script.pl

还有相当广泛的第 3 方文章https://electiclight.co/2020/08/13/macos-version-numbering-isnt-so-simple/


为 Big Sur 或更高版本编译的应用程序将恢复“11.0”作为操作系统版本。

为早期版本编译的应用程序获得“10.16”。这个逻辑假设 10 作为前缀就不会被破坏。

环境变量

SYSTEM_VERSION_COMPAT
可以用来控制返回哪个版本的文件;
SYSTEM_VERSION_COMPAT=0 cat /System/Library/CoreServices/SystemVersion.plist
返回
11.0.1
,而
SYSTEM_VERSION_COMPAT=1 cat /System/Library/CoreServices/SystemVersion.plist
返回
10.16
。 (请注意,在
cat
的赋值和调用之间应该有一个空格,而不是换行符,这样 shell 会将其视为瞬态环境变量赋值,而不是非导出 shell 变量的赋值)。


2
投票

在修复此错误之前,这是一个快速修复。

import subprocess
p = subprocess.Popen("sw_vers", stdout=subprocess.PIPE)
result = p.communicate()[0]
print(result)

基本上直接从 shell 获取版本,希望这有帮助。


0
投票

platform.mac_ver()
为您提供 Kernal 版本。

如果您需要动态获取当前 Mac 的操作系统名称。 我构建这个是为了尝试解决问题。 这可能是过度煮熟的代码,但是它确实有效。哈哈

https://github.com/JayRizzo/JayRizzoTools/blob/master/pyMacOsName.py

我的代码将返回操作系统的元组以及内部版本号。 ('macOS'、'蒙特利'、'12.4'、'21F79')

如果您想以不同的方式使用它:https://github.com/JayRizzo/JayRizzoTools/blob/master/pyHeaderMac.py这用于生成下面代码中显示的标头。 (前 10 行)

具体

# Created Syst: macOS Monterey 12.4 (21F79) Kernel: Darwin 21.5.0
都是动态生成的。

如果您只需要获取名称,请查看我的代码末尾以查看一些示例。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Created Syst: macOS Monterey 12.4 (21F79) Kernel: Darwin 21.5.0
# Created Plat: Python 3.9.5 ('v3.9.5:0a7dcbdb13', 'May  3 2021 13:17:02')
# Created By  : Jeromie Kirchoff
# Created Date: Mon Jun 13 15:22:59 2022 CDT
# Last ModDate: Tue Jun 21 20:59:51 2022 CDT
# =============================================================================
# Notes: Version 2 Class
# =============================================================================

import subprocess
from os import linesep

class MacOSName(object):
    """Setup INIT for MacOSName.
    List Derived From: https://apple.stackexchange.com/a/334337/55628
    This takes the "Major" & "Minor" Versions to generate the name & compares it to sw_vers()
    """
    def __init__(self):
        # super(MacOSName, self).__init__()
        self.escappedTab    = str(r'\t'),
        self.version        = "",
        self.productName    = "",
        self.oSNameFrmVer   = "",
        self.productVersion = "",
        self.buildVersion   = "",
        self.p              = "",
        self.v              = "",
        self.m              = "",
        self.major          = "",
        self.minor          = "",
        self.found          = "",
        self.result         = "",
        self.verz           = "",
        self.macOS          = {"12.04"  : "Monterey", "12.4"   : "Monterey", "12.03"  : "Monterey", "12.3"   : "Monterey", "12.02"  : "Monterey", "12.2"   : "Monterey", "12.01"  : "Monterey", "12.1"   : "Monterey", "12.00"  : "Monterey", "12.0"   : "Monterey", "11.20"  : "Big Sur", "11.19"  : "Big Sur", "11.18"  : "Big Sur", "11.17"  : "Big Sur", "11.16"  : "Big Sur", "11.15"  : "Big Sur", "11.14"  : "Big Sur", "11.13"  : "Big Sur", "11.12"  : "Big Sur", "11.11"  : "Big Sur", "11.10"  : "Big Sur", "11.09"  : "Big Sur", "11.9"   : "Big Sur", "11.08"  : "Big Sur", "11.8"   : "Big Sur", "11.07"  : "Big Sur", "11.7"   : "Big Sur", "11.06"  : "Big Sur", "11.6"   : "Big Sur", "11.05"  : "Big Sur", "11.5"   : "Big Sur", "11.04"  : "Big Sur", "11.4"   : "Big Sur", "11.03"  : "Big Sur", "11.3"   : "Big Sur", "11.02"  : "Big Sur", "11.2"   : "Big Sur", "11.01"  : "Big Sur", "11.1"   : "Big Sur", "11.00"  : "Big Sur", "11.0"   : "Big Sur", "10.20" : "Catalina", "10.19" : "Catalina", "10.18" : "Catalina", "10.17" : "Catalina", "10.16" : "Catalina", "10.15" : "Catalina", "10.14" : "Mojave", "10.13" : "High Sierra", "10.12" : "Sierra", "10.11" : "X El Capitan", "10.10" : "X Yosemite", "10.09" : "X Mavericks", "10.9"  : "X Mavericks", "10.08" : "X Mountain Lion", "10.8"  : "X Mountain Lion", "10.07" : "X Lion", "10.7"  : "X Lion", "10.06" : "X Snow Leopard", "10.6"  : "X Snow Leopard", "10.05" : "X Leopard", "10.5"  : "X Leopard", "10.04" : "X Tiger", "10.4"  : "X Tiger", "10.03" : "X Panther", "10.3"  : "X Panther", "10.02" : "X Jaguar", "10.2"  : "X Jaguar", "10.01" : "X Puma", "10.1"  : "X Puma", "10.0"  : "X Cheetah", "10.00" : "X Cheetah" }

    def getOsName(self, verz):
        self.version = verz
        if isinstance(self.version, set):
            self.version         = ''.join(self.version)
            self.major           = self.version.split(".")[0]
            try:
                self.minor       = str(self.version).split(".")[1]
            except IndexError as e:
                self.minor       = 0
            except Exception as e:
                print(f"\n\n\t\t\tSET ERROR: {e}")
            try:
                for j, k in self.macOS.items():
                    self.v = j.split('.')[0]
                    self.m = j.split('.')[1]
                    if self.v == self.major:
                        if self.m == self.minor:
                            self.found = k
                            break
            except Exception as e:
                print(f"\n\n\t\t\tERROR: {e}")

        elif isinstance(self.version, str):
            self.version         = ''.join(self.version)
            self.major           = self.version.split(".")[0]
            try:
                self.minor       = str(self.version).split(".")[1]
            except IndexError as e:
                self.minor       = 0
            except Exception as e:
                print(f"\n\n\t\t\tSTRING ERROR : {e}")
            try:
                for j, k in self.macOS.items():
                    self.v = j.split('.')[0]
                    self.m = j.split('.')[1]
                    if self.v == self.major:
                        if self.m == self.minor:
                            self.found = k
                            break
            except Exception as e:
                print(f"\n\n\t\t\tERROR: {e}")
        return self.found

    def getCurrentSystemInfo(self):
        self.p              = subprocess.Popen("/usr/bin/sw_vers", shell=True, stdout=subprocess.PIPE)
        self.result         = self.p.communicate()[0]
        self.result         = self.result.decode("utf-8").split(str('\t'))
        self.productName    = self.result[1].split(linesep)[0]
        self.productVersion = self.result[2].split(linesep)[0]
        self.buildVersion   = self.result[3].split(linesep)[0]
        self.oSNameFrmVer   = self.getOsName({'12.4'})
        self.productName    = self.result[1].split('\n')[0]
        # # return Example: ('macOS', 'Monterey', '12.4', '21F79')
        return self.productName, self.oSNameFrmVer, self.productVersion, self.buildVersion

    def main(self):
        return

if __name__ == '__main__':
    print(f"{MacOSName().getCurrentSystemInfo()}")  # Returns TUPLE('macOS', 'Monterey', '12.4', '21F79')
    a = MacOSName().getCurrentSystemInfo()
    pt = a[0] # Product Type
    pn = a[1] # Product Name
    pv = a[2] # Product Version
    pb = a[3] # Product Build Number
    print(f"""
Product Type        : {pt}
Product Name        : {pn}
Product Version     : {pv}
Product Build Number: {pb}
""")
    # Product Type        : macOS
    # Product Name        : Monterey
    # Product Version     : 12.4
    # Product Build Number: 21F79
    # # Supports String Versions
    print(f"{MacOSName().getOsName('11.4')}")           # Returns Name  Big Sur
    print(f"{MacOSName().getOsName('11.04')}")          # Returns Name  Big Sur
    print(f"{MacOSName().getOsName('11.14')}")          # Returns Name  Big Sur
    print(f"{MacOSName().getOsName('10.02')}")          # Returns Name  Mojave
    print(f"{MacOSName().getOsName('10.9')}")           # Returns Name  X Mavericks
    print(f"{MacOSName().getOsName('10.09.424.24')}")   # Returns Name  X Mavericks  (ignores any subversion)
    # # Supports Sets Versions
    print(f"{MacOSName().getOsName(set({'11.4'}))}")    # Returns Name  Big Sur
    print(f"{MacOSName().getOsName(set({'11.4.2'}))}")  # Returns Name  Big Sur
    # Error:
    print(f"{MacOSName().getOsName('75.02')}")          # Returns Name  Empty Tuple

0
投票

TL;Charles Duffy 的回答的博士:

export SYSTEM_VERSION_COMPAT=0

之后,Python 的

platform.mac_ver()
应该报告正确的 MacOS 版本。

© www.soinside.com 2019 - 2024. All rights reserved.