Windows10におけるPython環境構築とは
本当に、一つの事しかしないのであればPythonの公式のバイナリをダウンロードして、パッケージのインストールにpipを使ってPyPIに集約された、いろいろな人が開発されたパッケージを使って構築してもいいと思います。ですが、Windowsの環境ではpipでは、絶妙に使いたいのにインストール出来ない場合も少なくないと思います。
また、使用されている方の多いAnacondaを使用するのも一つの手ではあると思いますがこれはこれで全部のせで、バージョンアップに時間がかかったり、複数の開発や分析をしている時に一つの開発のために同じパッケージのバージョンを上げると他の開発に思ってもないエラーが出たりして慌てることがあります。
そこで、使うのがAnacondaに内蔵されているパッケージ、仮想環境管理システムcondaです。これだけで、パッケージのインストール等の管理、仮想環境の管理が両方できます。
今回取り上げるのは、condaとpythonの最低限の状態で配布されているAnacondaの最小版Minicondaを使った環境構築について今回はメモしたいと思います。
あと、Windows上でcondaを使ってymlファイルでの環境の構築にバグがあってその対策方についても同時にメモします。
[2019/02/01 condaの仕様変更による大幅編集]
Minicondaを使った環境構築
流れとしては、
- Minicondaを使ってpythonをインストール
- condaをアップデートし、conda initでPowerShellで使えるようにする
- 使いたいPythonバージョンとパッケージ環境を作成
- channelにconda-forgeを追加
- ymlファイル等から環境を作成する
という感じになります。
1.Minicondaを使ってpythonをインストール
下記、公式サイトからダウンロードしてインストール。
このとき、全体か、個人に入れるかは推奨されているJust Meにします。
これにすると「C:\Users\{ユーザー名}」内にインストールされます。逆にall usersだとprogram filesに入るので他のユーザと共有するので勝手にパッケージを消されたりしたりしたら困るのであまり良くないと思います。
また、以前に記事にしたようにadministoratorの権限なしで使っている時に不具合もあったのでJust Meで使っています。
hytmachineworks.hatenablog.com
condaの仕様が変更になり、activateとdeactivateによる切り替えからconda activateとconda deactivateによる切り替えに変わりました。これは、以前は、仮想環境へとactivateで切り替えをして、deactivateでデフォルトのpythonに戻っていました。語弊があるかもしれませんが、はじめからbaseという仮想環境にいて、それをconda activateで他の環境に移るような動作に変わっています。そのため、あえてpathを通さなくても良いと思います。なのでMinicondaの推奨通り下のようにオプションを選択します。
後は、次へ次へでいいと思います。
2.condaをアップデートし、conda initでPowerShellで使えるようにする
MinicondaでインストールしたPythonにpathが通っていないのでコマンドプロンプトやPowerShellでpythonとかcondaとか打っただけでは、エラーになってしまうのでAnaconda Promptを使ってcondaのアップデートをします。
Anaconda Promptはスタートメニューから下の画像のようにMinicondaであってもAnaconda3の中にあるので注意してください。
Anaconda Promptが立ち上がったらcondaのバージョンアップを行いましょう。以下のコマンドでバージョンアップ出来ます。
C:\Users\username>conda update conda
Solving environment: done## Package Plan ##
environment location: C:\Users\username\Miniconda3
added / updated specs:
- condaThe following packages will be UPDATED:
ca-certificates: 2018.03.07-0 --> 2018.12.5-0
certifi: 2018.8.24-py37_1 --> 2018.11.29-py37_0
conda: 4.5.11-py37_0 --> 4.6.2-py37_0
cryptography: 2.3.1-py37h74b6da3_0 --> 2.4.2-py37h7a1dbc1_0
openssl: 1.0.2p-hfa6e2cd_0 --> 1.1.1a-he774522_0
vc: 14-h0510ff6_3 --> 14.1-h0510ff6_4
vs2015_runtime: 14.0.25123-3 --> 14.15.26706-h3a45250_0The following packages will be DOWNGRADED:
yaml: 0.1.7-hc54c509_2 --> 0.1.7-vc14_0 conda-forge [vc14]
最新のcondaにアップデートされました。そうしたら、使うシェルを指定しましょう。
私は、PowerShellを使うので
conda init powershell
するとPowerShellのプロファイルもなければ作成、あれば修正されます。ここからは、PowerShellで進めてゆくのでAnaconda Promptを閉じます。そして、PowerShellを開いてみましょう。
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.パーソナル プロファイルとシステム プロファイルの読み込みにかかった時間は 546 ミリ秒です。
(base) PS C:\Users\username>
上記の様に開けていれば成功です。PSの隣に(base)と表示されていますが、現在有効な環境を確認するとbaseが有効であるとわかります。このように、常に自分の環境を意識して切り替えて使ってゆきます。
(base) PS C:\Users\username> conda info -e
# conda environments:
#
base * C:\Users\username\Miniconda3
※もし、実行できないというエラーがでた場合、.ps1のスクリプトの実行許可が付与されていないので。一度PowerShellを終了して。
Start > Windows PowerShell > Windows PowerShellで右クリックし、メニューから「管理者として実行する」をクリック
ユーザーアカウント制御のウインドウが表示されるので許可してあげてください。すると管理者:Windows PowerShellというウィンドウが開かれるので下記コマンドを実行してください。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
実行ポリシーの変更を聞かれるので「yと入力してエンター」をして許可して上げてください。
3.使いたいPythonバージョンとパッケージ環境を作成
例えば、python 3.4のpy34という名前の環境の作成は
conda create -n py34 python=3.4
で、作成されます。ここで、python=3.4としていますが、この指定法だとpython 3.4のなかで最新この場合は3.4.5がインストールされます。もしマイナーバージョンまで指定が必要であればpython=3.4.1を入れるのであれば
conda create -n py34 python=3.4.1
と指定します。このバージョンの指定方法はパッケージを入れるときも同様に行えます。また、バージョンの指定を行わない場合は最新版がインストールされます。試しにやってみると以下の様にpython3.7.2がインストールされています。
(base) PS C:\Users\username> conda create -n pylatest python
Collecting package metadata: done
Solving environment: done## Package Plan ##
environment location: C:\Users\username\Miniconda3\envs\pylatest
added / updated specs:
- pythonThe following NEW packages will be INSTALLED:
ca-certificates pkgs/main/win-64::ca-certificates-2018.12.5-0
certifi pkgs/main/win-64::certifi-2018.11.29-py37_0
openssl pkgs/main/win-64::openssl-1.1.1a-he774522_0
pip pkgs/main/win-64::pip-18.1-py37_0
python pkgs/main/win-64::python-3.7.2-h8c8aaf0_0
setuptools pkgs/main/win-64::setuptools-40.6.3-py37_0
sqlite pkgs/main/win-64::sqlite-3.26.0-he774522_0
vc pkgs/main/win-64::vc-14.1-h0510ff6_4
vs2015_runtime pkgs/main/win-64::vs2015_runtime-14.15.26706-h3a45250_0
wheel pkgs/main/win-64::wheel-0.32.3-py37_0
wincertstore pkgs/main/win-64::wincertstore-0.2-py37_0
Proceed ([y]/n)? y
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
# $ conda activate pylatest
#
# To deactivate an active environment, use
#
# $ conda deactivate
最後に出ているように上で作成したpylatestという環境に移るには
conda activate pylatest
逆に出るには、以下のコマンドで出ることが出来ます。
conda deactivate
作成された環境の一覧を確認するのは、以下のコマンドで確認。現在アクティブな環境に名前の後に*がついています
(base) PS C:\Users\username> conda info -e
# conda environments:
#
base * C:\Users\username\Miniconda3
py34 C:\Users\username\Miniconda3\envs\py34
pylatest C:\Users\username\Miniconda3\envs\pylatest
試しに、環境を切り替えて確認してみます。py34に切り替えてみます。
(base) PS C:\Users\username>conda activate py34
(py34) PS C:\Users\username>
PSの前に環境名(py34)がついたと思います。また、環境一覧を見ると
(py34) PS C:\Users\username> conda info -e
# conda environments:
#
base C:\Users\username\Miniconda3
py34 * C:\Users\username\Miniconda3\envs\py34
pylatest C:\Users\username\Miniconda3\envs\pylatest
ちゃんとpy34に移ってますね。元に戻す場合は、
(py34) PS C:\Users\username> conda deactivate
(base) PS C:\Users\username>
PSの前の環境名が外れてますね。また、環境一覧を見ると
(base) PS C:\Users\username> conda info -e
# conda environments:
#
base * C:\Users\username\Miniconda3
py34 C:\Users\username\Miniconda3\envs\py34
pylatest C:\Users\username\Miniconda3\envs\pylatest
元のbaseに戻ってますね。環境を使わなくなった場合は、試しにpy34を消すのは
(base) PS C:\Users\username> conda env remove -n py34
Remove all packages in environment C:\Users\username\Miniconda3\envs\py34:
環境一覧を見ると
(base) PS C:\Users\username> conda info -e
# conda environments:
#
base * C:\Users\username\Miniconda3
pylatest C:\Users\username\Miniconda3\envs\pylatest
ちゃんと消えてますね。
ちなみに、環境を作る時に同時にパッケージをインストールも可能で例えばnumpyとscipyを同時にインストールであればスペースで区切って入れれば同時に環境が作成されます。
conda create -n py34 python=3.4 numpy scipy
また、ここで、anacondaを指定するとanacondaを入れたのと同じ事になります。
環境作成後に、環境に対してパッケージを入れる場合は、py34という環境にpandasを入れる場合は -n で環境名を指定してあげてインストール出来ます。
conda install pandas -n py34
もしくは、conda activateを用いて一旦、環境を有効にしてからインストールも出来ます。
conda activate py34
conda install pandas
のどちらでも可能です。ちなみに、私は -n をつけて行う方が多いです。
4.channelにconda-forgeを追加
condaでパッケージをインストールする際に、パッケージのデータベース、condaではchannelと読んでいる物へ探しに行くのですが、デフォルトだとたまに無いことがあってその時にお世話になるのが、conda-forgeです。-c conda-forgeという感じで指定することもできるのですがデフォルトで検索対象に加えてしまいましょう。
conda config --append channels conda-forge
追加されたか確認すると
(base) PS C:\Users\username> conda config --get channels
--add channels 'conda-forge' # lowest priority
--add channels 'defaults' # highest priority
ちゃんと追加されていますね。
5.ymlファイル等から環境を作成する
まず、例を示すために環境を作成します。
conda create -n py34 python=3.4 numpy scipy
この環境をymlファイルに書き出す方法は、
conda env export -n py34 > py34.yml
[2019/02/07 追記はじめ]
このコマンドは間違っています。正確には、
conda env export -n py34 -f py34.yml
です。" > "でなくて、" -f "でしたこうすればちゃんとUTF-8で保存されて下の
conda env create -n py34 -f py34.yml
で復元出来ます。ですが、初めのコマンドは、PowerShellの機能ので
conda env export -n py34
の出力結果をpy34.ymlに対して書き出す。っていうコマンドになっていました。それが、おかしなエンコードになった原因でした。そのおかしなコマンドで慌ててやった色んなことの結果が以下に続いています。pipとの話もあるので最後まで読んでいただけると幸いです。
[2019/02/07 追記おわり]
現在のフォルダにpy34.ymlが保存されると思います。
一回、py34の環境を削除してそのファイルを使ってpy34という環境を作成してみましょう。
(base) PS C:\Users\username> conda env create -n py34 -f py34.yml
# >>>>>>>>>>>>>>>>>>>>>> ERROR REPORT <<<<<<<<<<<<<<<<<<<<<<
Traceback (most recent call last):
File "C:\Users\username\Miniconda3\lib\site-packages\conda\exceptions.py", line 1001, in __call__
return func(*args, **kwargs)
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\cli\main.py", line 73, in do_call
exit_code = getattr(module, func_name)(args, parser)
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\cli\main_create.py", line 77, in execute
directory=os.getcwd())
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\specs\__init__.py", line 40, in detect
if spec.can_handle():
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\specs\yaml_file.py", line 18, in can_handle
self._environment = env.from_file(self.filename)
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\env.py", line 131, in from_file
return from_yaml(yamlstr, filename=filename)
File "C:\Users\username\Miniconda3\lib\site-packages\conda_env\env.py", line 116, in from_yaml
data = yaml_load_standard(yamlstr)
File "C:\Users\username\Miniconda3\lib\site-packages\conda\common\serialize.py", line 76, in yaml_load_standard
return yaml.load(string, Loader=yaml.Loader, version="1.2")
File "C:\Users\username\Miniconda3\lib\site-packages\ruamel_yaml\main.py", line 638, in load
loader = Loader(stream, version, preserve_quotes=preserve_quotes)
File "C:\Users\username\Miniconda3\lib\site-packages\ruamel_yaml\loader.py", line 46, in __init__
Reader.__init__(self, stream, loader=self)
File "C:\Users\username\Miniconda3\lib\site-packages\ruamel_yaml\reader.py", line 80, in __init__
self.stream = stream # type: Any # as .read is called
File "C:\Users\username\Miniconda3\lib\site-packages\ruamel_yaml\reader.py", line 112, in stream
self.check_printable(val)
File "C:\Users\username\Miniconda3\lib\site-packages\ruamel_yaml\reader.py", line 233, in check_printable
'unicode', "special characters are not allowed")
ruamel_yaml.reader.ReaderError: unacceptable character #x0000: special characters are not allowed
in "<unicode string>", position 3以下略
py34.ymlに書いて文字が読めねーぞって怒られてます。ここがハマりポイント!
っていうかネットで誰も困って無いのが不思議なんだけどね。Linuxとかでは普通に読み込めるエンコードで書き出されるのかな?
エンコードが怪しいって事で 以前、取り上げたchardetを使って以下の内容のconda_chardet.pyを作成。もし、utf-8じゃなかったら保存し直すようにしてある。
from chardet.universaldetector import UniversalDetector
import sys
def file_encoding_detect(file_path):
""" detect text file encoding
:param file_path: file path string
:return: encoding string
"""
detector = UniversalDetector()
with open(file_path, mode="rb") as f:
read_data = f.readlines()
for line_data in read_data:
detector.feed(line_data)
if detector.done:
break
detector.close()
detect_result = detector.result
if detect_result["encoding"]:
detect_encoding = detect_result["encoding"]
else:
raise KeyError("Expected file is not text file!!!")
return detect_encoding
def main():
""" detect file encoding
:return: encoding string
"""
args = sys.argv
if len(args) < 2:
raise KeyError("File is not set")
file_yml = args[1].strip(".\\")
file_encoding = file_encoding_detect(file_yml)
print(file_encoding)
if file_encoding not in ["ascii", "utf-8"]:
with open(file_yml, mode="r", encoding=file_encoding) as fr:
data = fr.read()
mod_yml = "_mod.".join(file_yml.split("."))
with open(mod_yml, mode="w", encoding="utf-8") as fw:
fw.write(data)
message = "{old} saved new file {new} with encoding utf-8"
print(message.format(old=file_yml, new=mod_yml))
if __name__ == "__main__":
main()
そして、そのconda_chardet.pyとpy34.ymlを同じディレクトリにおいて実行すると
(base) PS C:\Users\username> python conda_chardet.py py34.yml
UTF-16
py34.yml saved new file py34_mod.yml with encoding utf-8
という訳で、UTF-8でなくUTF-16なので読めないのが原因です。そんな訳でutf-8で保存したファイルで実行してみると
(base) PS C:\Users\username> conda env create -n py34 -f py34_mod.yml
Collecting package metadata: done
Solving environment: done
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
# $ conda activate py34
#
# To deactivate an active environment, use
#
# $ conda deactivate
出来ているか環境一覧を見ると
(base) PS C:\Users\username> conda info -e
# conda environments:
#
base * C:\Users\username\Miniconda3
py34 C:\Users\username\Miniconda3\envs\py34
pylatest C:\Users\username\Miniconda3\envs\pylatest
ちゃんとできてますね。 パッケージも確認すると
(base) PS C:\Users\username> conda list -n py34
# packages in environment at C:\Users\username\Miniconda3\envs\py34:
#
# Name Version Build Channel
blas 1.0 mkl
intel-openmp 2019.1 144
mkl 2017.0.4 h6d528fc_0
numpy 1.11.3 py34_0
pip 9.0.1 py34_1
python 3.4.5 0
scipy 0.19.1 np111py34_0
setuptools 27.2.0 py34_1
vc 10 0
vs2010_runtime 10.00.40219.1 2
wheel 0.29.0 py34_0
python 3.4で、numpyとscipyがちゃんとインストールされてますね。
今回は、エンコード確認から、変更までpythonでやりましたが別にテキストエディタでエンコードを指定して保存すれば大丈夫です。ただ、UTF-8のBOM無し(UTF-8N)で保存する必要があります。
一応、これで一通り環境構築はできると思います。皆さんのお役にたてば幸いです。
[2019/02/01 condaの仕様変更による大幅編集のメモ]
以下で、触れているPowerShellへの対応と、pipとの相互乗り入れへの試験適用と結構盛りだくさんな内容です。当分目が離せなさそうです。
[2019/02/02 pipとの相互乗り入れを試したので追記]
参考までに、pipと相互乗り入れを可能にするコマンド
conda config --set pip_interop_enabled True
これを実行するとPyPiからのパッケージは、pipからインストールしなくてはいけませんが、その後のパッケージの削除や、バージョン変更等はcondaから行えます。
元に戻すのは、逆にFalseにして
conda config --set pip_interop_enabled False
で元に戻ります。この状態だとpipとcondaで同じパッケージを入れてもpipで入れた方しか見えなくなるみたい。そのうえでcondaからは消せないっていう状態になるみたい。前みたいにpipとcondaで入れたものが並列に並ぶ事は無くなったみたい。
どっちの状態でもpipで入れるとconda listではチャンネルがpypiというような表現に変わっています。でも、conda からチャンネルをpypiでやっても入りません。
また、状況がかわったら更新します。