Volo di notte

お勉強の成果メモや日常のこと

夜間飛行へ移行中です

 

Windows版Python 2.7 64bit版でCython

2018/1/17 追記: Python3系についても困った場合について、対策を記事にしました:Python環境でVisual StudioのCコンパイラのエラーに困ったら… - 夜間飛行
Python 2.7でも同じ対策でなんとかなれば幸いです。

ディープラーニングフレームワーク Chainerなどで使われるnVidia CUDAなども64bit版のみのサポートになるなど、Python2.7の環境も64bitへの移行を余儀なくされました。

その一方でWindowsの環境だとPython 64bit版ではCythonがうまく動かないという問題もあり、ちょっとぐぐって調べてみてもCythonはPython 64bit Windows版に対応しないとまで言及されています[1]。

これに対して、Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1を使えば解決できるという情報があったものの[2][3]、なんとかMicrosoft Visual C++ Compiler for Python 2.7だけでCythonを使えたので、覚書として残します。

(Cythonというよりdistutilの問題である気がしますが…)

0. 環境

1. Python 2.7へVisual C++の設定

Python2.7の32bit版でもVC++を使う場合は同じことをします。

まずC:/Python27/Lib/distutils/distutils.cfgの中身の書き換えて、Visual C++を使うようにします
(distutils.cfgがない場合は作成する)

[build]
compiler=msvc

このままだと

error: Unable to find vcvarsall.bat

というエラーが出てしまいVC++コンパイラーが見つけられないので、 C:/Python27/Lib/distutils/msvc9compiler.pyのfind_vcvarsallを下記のようにコードを追加します。
([2]を参考にしました)

def find_vcvarsall(version):
    """Find the vcvarsall.bat file

    At first it tries to find the productdir of VS 2008 in the registry. If
    that fails it falls back to the VS90COMNTOOLS env var.
    """
    vsbase = VS_BASE % version
    #---Patch----
    vcpath = os.environ['ProgramFiles']
    vcpath = os.path.join(vcpath, 'Common Files', 'Microsoft',
        'Visual C++ for Python', '9.0', 'vcvarsall.bat')
    if os.path.isfile(vcpath): return vcpath
    vcpath = os.path.join(os.environ['LOCALAPPDATA'], 'Programs', 'Common', 'Microsoft', 'Visual C++ for Python', '9.0', 'vcvarsall.bat')
    if os.path.isfile(vcpath): return vcpath
    #-------------

2. Python 2.7 - 64bit版でのCython

VC++で64bit版のオブジェクトを作成するために毎回実行しなくてはいけないというのがいけてないですが、 次の手順でVC++の環境を設定していきます。

VC++用にコマンドプロンプトを64bitの環境設定で起動する

    スタートメニュ > Microsoft Visual C++ Compiler Package for Python 2.7
    > Visual C++ 2008 64-bit Command Prompt

コンパイラが出力するオブジェクトを64bit版に設定する

set DISTUTILS_USE_SDK=1
setenv /x64 /release

うまくいくと字が緑色になります。

f:id:Chachay:20160606230851p:plain

このとき、環境変数が上書きされてしまっているので、Pythonへのパスが通るようにする

set path=C:\Python27\;C:\Python27\Scripts;%path%

VC++コンパイラcl.exeとlink.exeにパスが通るようにする

set path=C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for    
Python\9.0\VC\bin\amd64;C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Bin\x64;%path%
VC

VC++コンパイラのincludeフォルダへのパスを設定する。 libpathは設定しても有効ではなさそうです。

set include=C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Include;C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include;%include%

この状態でCythonizeしたいpyxファイルが置いてあるフォルダへ移動して、

python setup.py build_ext --inplace

を実行すると、Cythonizeとコンパイルが正常に実行された後、リンカがエラーを吐きます。 ライブラリにパスが通っていないためですが、前述の通りlibpathの設定では対処できないので、 setup.pyを書き換えます。Cython 事始め - 雑食性雑感雑記の例を下敷きにした変更ですと[4]

#! -*- coding: utf-8 -*-
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
 
ext_modules = [
    Extension( "calculate", ["calculate.pyx"],
    extra_compile_args=[],
    extra_link_args=[
        "/LIBPATH:C:\Users\(ユーザー名)\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\lib\\amd64", 
        "/LIBPATH:C:\Users\(ユーザー名)\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Lib\\x64"
    ]
    ),
]
setup(
    name = "Sample calculate app",
    cmdclass = { "build_ext" : build_ext },
    ext_modules = ext_modules,
)

改めて

python setup.py build_ext --inplace

を実行するとpydファイルが作成され、出来上がり

3. 2. のまとめ

Visual C++ 2008 64-bit Command Promptを起動し、以下を実行

set DISTUTILS_USE_SDK=1
setenv /x64 /release
set path=C:\Python27\;C:\Python27\Scripts;%path%
set path=C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\bin\amd64;C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Bin\x64;%path%
set include=C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Include;C:\Users\%USERNAME%\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include;%include%
cd (pyxを置いてあるワークディレクトリへ移動)
python setup.py build_ext --inplace

そして、setup.pyにはリンカオプションをつけておく

ということでした。

[参考文献]

[1] akorn / wheezy.template / issues / #10 - Installation on windows fails — Bitbucket
https://bitbucket.org/akorn/wheezy.template/issues/10/installation-on-windows-fails#comment-12006152

[2]CythonExtensionsOnWindows · cython/cython Wiki · GitHub
https://github.com/cython/cython/wiki/CythonExtensionsOnWindows

[3] cython を windows 64bit 版で使う方法 - researchmap
http://researchmap.jp/jo9jywwyp-23687/

[4] Cython 事始め - 雑食性雑感雑記
http://kazuki-nagasawa.hatenablog.com/entry/start_cython