Windows平臺python 編譯C "error: Microsoft Visual C++ 9.0 is required"

關鍵詞: python插件,  visual studio,  Windows編譯

1. 背景知識

1.1 關于Python編譯

目前,我們使用的Python大部分屬于CPython,也就是用C語言實現的Python版本。本質上來講,無論是在Linux還是Windows平臺下,我們使用的都是C編譯器編譯后的(python)可執行程序。不同點在于,Linux平臺源碼安裝(默認的C編譯器一般為gcc)python,C/C++編譯環境在本地;Windows平臺則通過下載編譯好的Python安裝使用,本地不一定具備C/C++編譯環境。

編譯Python使用的編譯器版本信息可在python版本信息中查看:

#########################
## 該Linux平臺上安裝的python是經過GCC 5.4.0版編譯器
## 編譯生成的python 2.7.12 版
python
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
>>> import sys
>>> sys.version
2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609]
#########################
## 該Windows平臺上安裝的python是經過Visual C++ 9.0版編譯器
## 編譯生成的python 2.7.14 版
python
Python 2.7.14 | packaged by conda-forge | (default, Dec 25 2017, 01:17:32) [ MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.version
2.7.14 | packaged by conda-forge | (default, Dec 25 2017, 01:17:32) [MSC v.1500 64 bit (AMD64)]

為保證兼容性,使用pip給python添加擴展/模塊時,如果擴展/模塊中包含有C/C++源碼,安裝腳本將試圖尋找與編譯生成Python的同版本編譯器來編譯生成該模塊。也就是說在上述兩個平臺下,Linux平臺將尋找并使用GCC 5.4.0 來編譯生成Python擴展/模塊,Windows平臺將尋找并使用Visual C++ 9.0 來編譯生成Python擴展/模塊。

1.2 關于編譯器版本

上面說過,編譯生成Python的編譯器及版本信息可以在Python的版本信息中查看。通常情況下,Linux平臺能夠保證Python編譯生成環境和Python擴展/模塊編譯生成環境的一致性,使用中不會存在什么問題。所以本節將主要討論Windows下的C/C++編譯器。

Windows平臺下的C/C++編譯器默認是 Microsoft Visual C++ (下面簡稱VC)。VC常作為Microsoft Visual Studio(以下簡稱VS) 開發套件的組成部分在 VS安裝時被安裝在設備上,我們通常不單獨安裝VC。特別需要注意的是不同版本 的VS搭載不同版本的VC,其對應關系如下:

VS版本 內部版本 VC版本
Visual Studio 4.0 Visual C++ 4.0
Visual Studio 97 5.0 Visual C++ 5.0
Visual Studio 6.0 6.0 Visual C++ 6.0
Visual Studio .NET 2002 7.0 Visual C++ 2002
Visual Studio .NET 2003 7.1 Visual C++ 2003
Visual Studio 2005 8.0 Visual C++ 2005
Visual Studio 2008 9.0 Visual C++ 2008
Visual Studio 2010 10.0 Visual C++ 2010
Visual Studio 2012 11.0 Visual C++ 2012
Visual Studio 2013 12.0 Visual C++ 2013
Visual Studio 2015 14.0 Visual C++ 2015
Visual Studio 2015 RTM 14.0 Visual C++ 2015

所以如果你需要使用 VC 9.0 即 VC 2008,則你需要 安裝VS 2008 或 VS 2008 Express 版本才行。

1.3 編譯 Python 的VC版本

從 Python的版本信息可以看出:雖然我們能夠知道編譯生成Python的環境信息(MSC v.1500 64 bit (AMD64)),但不難發現這和上節所講的編譯器版本上沒有直觀的聯系,那么將如何通過條信息推斷相應的VC版本呢?

在Python安裝目錄的子目錄Lib/distutils中,msvccompiler.py 和 msvc9compiler.py 包含了編譯器相關的操作。我們先看看兩個文件的注釋:

"""distutils.msvccompiler

Contains MSVCCompiler, an implementation of the abstract CCompiler class
for the Microsoft Visual Studio.
"""
"""distutils.msvc9compiler

Contains MSVCCompiler, an implementation of the abstract CCompiler class
for the Microsoft Visual Studio 2008.

The module is compatible with VS 2005 and VS 2008. You can find legacy support
for older versions of VS in distutils.msvccompiler.
"""

在這兩個文件中定義了一個函數 get_build_version 從python版本信息中抽取編譯版本信息,計算并返回編譯生成Python的VC版本信息,函數實現如下:

def get_build_version():
    """Return the version of MSVC that was used to build Python.

    For Python 2.3 and up, the version number is included in
    sys.version.  For earlier versions, assume the compiler is MSVC 6.
    """

    prefix = "MSC v."
    i = string.find(sys.version, prefix)
    if i == -1:
        return 6
    i = i + len(prefix)
    s, rest = sys.version[i:].split(" ", 1)
    majorVersion = int(s[:-2]) - 6
    minorVersion = int(s[2:3]) / 10.0
    # I don't think paths are affected by minor version in version 6
    if majorVersion == 6:
        minorVersion = 0
    if majorVersion >= 6:
        return majorVersion + minorVersion
    # else we don't know what version of the compiler this is
    return None

結合節1.1 中所示的python版本信息來推演一遍,過程如下:

  1. 先提取 MSC v. 字符串后的版本號 1500
  2. 計算 majorVersion = 15-6 和 minorVersion = 0 / 10.0
  3. 返回 majorVersion+minorVersion = 9.0

所以在1.1節的環境下,要編譯生成python擴展/模塊腳本將尋找并使用9.0 版本的VC 編譯器。根據 get_build_version 提供的邏輯,只要知道python的詳細版本信息就能夠推理出所需要的VC版本。

實際上,MSC v. 后面跟的數字并不是隨意的、為滿足 get_build_version 計算而生成的數字,他們是微軟為編譯器定義的數字版本號碼,只是編譯器版本和數字版本號碼之間有如 get_build_version 所描述的對應關系。下面列出一些對應關系:

VC版本 數字版本號
Visual C++ 4.x MSC_VER=1000
Visual C++ 5 MSC_VER=1100
Visual C++ 6 MSC_VER=1200
Visual C++ .NET MSC_VER=1300
Visual C++ .NET 2003 MSC_VER=1310
Visual C++ 2005 MSC_VER=1400
Visual C++ 2008 MSC_VER=1500
Visual C++ 2010 MSC_VER=1600
Visual C++ 2012 MSC_VER=1700
Visual C++ 2013 MSC_VER=1800

知道對應的VC版本后,接下了就是找到該版本VC 編譯器的物理路徑。腳本在尋找VC路徑的時候遵循 “先注冊表---后環境變量” 的順序。對于 VC版本>=9.0的情形,腳本通過 HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\ VC版本 \ Setup\VC\ProductDir (64位Python) 或 HKLM\SOFTWARE\Microsoft\VisualStudio\ VC版本 \ Setup\VC\ProductDir (其他情況)鍵值獲取VC編譯器的路徑。若該鍵不存在則通過 環境變量 “VS@0COMNTOOLS” 來確定VC 編譯器路徑,其中@ 為VC主版本號。具體的尋徑策略見 msvc9compiler.py (vc_major>8) 或 msvccompiler.py (低版本)。

2. 解決方案

在用pip為Python安裝擴展/模塊時,出現錯誤 “error: Microsoft Visual C++ 9.0 is required” 說明安裝腳本沒有在安裝平臺上找到所需要的 9.0 版本的VC 編譯器。這種錯誤通過安裝VS 2008 或者 VS 2008 Express 一定能夠解決,因為安裝軟件時會自動設置注冊表信息和環境變量信息。

考慮到python的廣泛使用性,Microsoft 發布了用于編譯python的vc 編譯器。通過安裝相應版本的程序,用戶可為python提供匹配的VC編譯環境,從而避免安裝VS。這里給出 Python 2.7 對應的 VC 9.0 編譯器 Microsoft Visual C++ Compiler for Python 2.7下載地址 :
https://www.microsoft.com/en-us/download/details.aspx?id=44266
http://aka.ms/vcpython27

需要說明的是僅僅通過安裝 VC for Python 還不夠,因為這個軟件在安裝過程中既不會設置注冊表也不會設置環境變量,所以即使完成了安裝也依然會出現找不到編譯器的問題。這時可通過手動設置注冊表或環境變量的方法排除問題。考慮到腳本路徑搜索時,注冊表信息對環境變量信息的覆蓋作用,以下幾個設置方式行之有效:

  1. 正確設置相應注冊表信息 (參見節1.3),此時環境變量設置與否、正確與否不影響使用
  2. 刪除VC版本對應的注冊表信息(參見節1.3),正確設置環境變量
  3. 正確設置注冊表信息+正確設置環境變量信息

通過上述設置,該問題得以解決。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容