Python のパッケージ管理ツールの簡単なまとめ
最近寒すぎて歩くのがつらく、走って帰っています(これはこれでつらい)。
Python を始めてまだ1ヶ月か2ヶ月ほどですが、始めたときに???ってなったことをちまちまと整理していきます。
今回は、パッケージ管理ツールの回りをまとめたいと思います。
先に断っておくと、詳しい話は他の詳しい方に任せてます。自分と同じように Python 始めたけど専門用語が飛び交いすぎて訳が分からない!となっている人に向けて、道しるべになるような簡単な解説にとどめたいと思っています。
パッケージングツールとパッケージインストーラ
パッケージ管理ツールを大きく分けるとパッケージングツールとパッケージインストーラの二つになります。
パッケージングツール
自作したライブラリを外部へ配布する際に使用するツール。PyPI で配布されているパッケージは、全てパッケージングツールを使ってパッケージ化されたものです。ツールは複数あり、wheel
,setup.py sdist
(コマンド),setuptools
,distutils
,distribute
などがこちらに当たります。現在は、wheel
が普及しています。パッケージインストーラ
PyPI などで公開されているパッケージをインストールするためのツール。一度は使ったことがあるかもしれません。pip
,easy_install
などがこちらに当たります。現在はpip
が普及しています。easy_install は、setuptools のコマンドラインツールだそうです。
パッケージングツールは複数あります。現在使われているのは、 wheel ですが、そこまで行き着くのにややこしい問題があったようです。特にややこしいのは、setuptools と distribute です。setuptools が登場し(2011年?)、そのフォーク(派生のようなもの)が distribute です(2012年?)。一時期は distribute を使うべきでしたが、2013年に setuptools にマージされます(がっちゃんこ)。
Python 3.3 までは pip がスタンダードで入っていなかったので自分で入れる必要がありました。そのため、setuptools (easy_install)を使って pip を入れていた時期があったようです。3.4 では pip は標準で入っていますので、setuptools(easy_install) を触る必要はありません。
distutils は、標準のパッケージ管理ツール(パッケージングもインストールも可能)です。setuptools や pip はこれを拡張したものだそうです。
さて、整理しましょう。最新の Python(3.4 以上)であれば、インストールするものは wheel だけです。そしてパッケージをインストールする際は、pip を使いましょう。以上です。
パッケージの配布形式
wheel
と egg
です。
昔は egg が使われていましたが、この egg にはいろいろ使いにくいところがありました。それを解決するために現れたのが wheel です。現在では、wheel が一般的に使われています。wheel 形式でパッケージするには、同じ名前のパッケージングツール wheel を使います。
異端児 Anaconda
(実際に使ったことがありませんので、間違いがあるかも……)
さて、さっきまで pip と wheel だけを使えば問題ないよと書いてきました。しかし、この Anaconda というやつには conda という便利なツールが存在します。こいつは、パッケージの管理と 仮想環境管理とバージョン管理が出来るようです。つまり pip, pyenv, virualenv の代わりを一人で担っています。また、パッケージングも行えます。ただし、wheel との互換性はないようです。研究で使う分には問題ないですが、開発となると今後扱いづらいかもしれません。
おわりに
パッケージ管理ツールをまとめると、通常は pip, wheel を使えばいいですが、考えるのが面倒くさい、さっさとコードを書く必要があるという人は、Anaconda をインストールして conda を使うという感じでしょうか。または、Anaconda でも pip は使えるので、パッケージ管理やパッケージングは、pip, wheel を使う(それ以外の環境回りは conda を使う)というのがいいかもしれません。
以上、つたない内容でしたが理解の一助になれば幸いです。
参考資料
歴史的な詳しい解説があります。とても参考になりました。 ymotongpoo.hatenablog.com
Anaconda(conda)の使い方が解説されています。 qiita.com
ちょっと情報が古いですが、よくまとまっているので、かなり参考になります。
Python パッケージ管理技術まとめ (pip, setuptools, easy_install, etc)
Python 3.6 から MySQL データベースへ SSH 接続を試みる
仕事中は、いろいろ書きたい記事を思いつくのですが、いざ書こうとするとネタが思いつかないことがよくあります。
メモ代わりにここに書きますが、カテゴリとしては、Python, MySQL, グラフ描画, ウィンドウハンドルを使った自動化。みたいな感じです。忘れないうちに書かないと……。
そうそう、Google Home を買ったので、それを使って遊んだりもしたい。今は、Python, MySQL が優先なので、そちらを身につけつつその間に Google Home について調べておこうかなと。
無駄話はこれぐらいにして、本題に入ります。
前回は、ローカル(PC 内に入っているデータベース(DB)への接続)な環境の話でしたが、今回は、ネットワーク上の DB への接続を試してみます。
以下を参考にしました。
環境の準備
まずは、今回使うモジュールを落としてきます。
pip install sshtunnel
ちなみにモジュールは、Github に公開されています。
これで SSH 接続するための環境は出来ました。 次は、実際にコードを書いて接続します。
SSH 接続を試みる
以下のコードを実行すると、SSH 接続するためのポート番号(何のポート番号かは分かっていません……)が出力されます。
# -*- coding: utf-8 -*- from sshtunnel import SSHTunnelForwarder import mysql.connector port_num = 22 with SSHTunnelForwarder( ('ip_address', port_num), ssh_username='user_name', ssh_password='user_pass', remote_bind_address=('127.0.0.1', 3306) ) as server: print(server.local_bind_port)
ip_address
には、接続したい DB がある IP アドレスを。port_num
には、SSH 接続のポート番号を(通常は、22)。remote_bind_address
には、DB がある IP アドレスとポート番号を指定するのですが、通常は、SSH 接続先にあると思うので、上記で問題ないと思います。
上手くいけば、ポート番号が表示されていると思います。
問題なければ SSH 接続が成功しています。with
を使わずに open()
, close()
のような方法もあります。以下のようにして、接続します。
port_num = 22 server SSHTunnelForwarder( ('ip_address', port_num), ssh_username='user_name', ssh_password='user_pass', remote_bind_address=('127.0.0.1', 3306) ) server.start() # 処理 server.stop()
start()
が open()
。stop()
が close()
の役割をしています。
では、次に出力したポート番号を使って DB へ接続します。
ここでは、前回使用したモジュール(mysql.connector
)を使って接続しています。
前回 pickles-ochazuke.hatenablog.com
conn = mysql.connector.connect( host = 'localhost', port = server.local_bind_port, user = 'user_name', password = 'user_pass', database = 'db_name', )
前回とほぼ変わりません。port のところに先ほど出力したポート番号を使っています。
おわり
以上です。とても簡単にできたと思います。
今回の SSH 接続の部分とは関係ありませんが、クエリを実行して、結果を取得する際に単純に受け取るとリストになると思います。一応これでも扱えるのですが、pandas のデータフレームというのを使うともっと便利に扱えるようになります。そこら辺も近いうちに書きたいと思います。
Python 3.6 で MySQL データベースに接続
お久しぶりです。
9月に就職が決定して、そこから空いた一週間で北の方を旅行して、仕事が始まって最初の一ヶ月は給料なくて、11月に初というか3,4ヶ月ぶりの給料でなんとか生活を凌いでいます。
前の仕事は、C言語だったんですけど、今の場所はすることによって言語が変わるそうで、今は Python をメインに触っています。あと初めて SQL を仕事で使っていまして、知らないことだらけで初めてコンピュータサイエンスを学んだ時のようで楽しいです。
さて、今月はなるべく更新をしたいなと思っていますので、小さい内容でも更新していきたいと思っています。主に仕事で学んだことをまとめる方向にしたいので、Python や SQL の話になるかなーと。
では、本題です。 以下を参考にしています。
環境構築
Python のバージョンは、3.6.3 です。
バージョンの確認は、コマンドプロンプトで python --version
を実行すれば確認できます。できなければ、パスが通ってないので、通しましょう。
まずは、必要なパッケージをインストールします。
pip install mysql-connector-python-rf
会社の環境だとプロキシの問題で、pip が上手くインストールしてくれないんですよね。そこら辺も覚えている範囲でまとめたい……。
mysql-connector-python
も必要っぽいので、以下から落としてきます。
https://pypi.python.org/pypi/mysql-connector-python
こだわりがなければ最新のやつを落としてください。私は、mysql-connector-python-8.0.5.tar.gz
を落としました。
落としたファイルの場所でコマンドプロンプトを開いて、以下を実行します。
pip install mysql-connector-python-8.0.5.tar.gz
そしたらインストールが成功するはずです。しなければ管理者権限でコマンドプロンプトを開いて、実行してみてください。
終わったら、pip list
で出力されたパッケージリストに今入れた二つがあるか確認します。
MySQL をインストールしていなければ、インストールしましょう。ここでは、その説明は除きます。MySQL サーバを立ち上げて、データベースとテーブルを作成して、準備完了です。
MySQL データベース(DB)への接続
まずは、接続です。各引数は、自身の環境に合わせて変えてください。
import mysql.connector conn = mysql.connector.connect( host = 'localhost', port = 3306, user = 'root', password = 'pass', database = 'test', )
とくにエラーが発生しなければ成功しているはずです。この conn
を使って、データベースに対していろいろ操作します。次に、接続が可能か調べるためには、以下を実行します。
connected = conn.is_connected() print(connected) if (not connected): conn.ping(True)
conn.is_connected()
によって接続が可能か真偽値で返ってきます。True の場合は、接続が可能で、False の場合は、接続が不可能な状態です。conn.ping(True)
は再接続を試みているのですが、conn.is_connected()
が False なら再接続で解決はしなさそうですね……環境に合わせた対処が必要になると思います。
conn.ping(True)
は、長い時間接続していると DB との接続が切れることがあるそうなので、その対処のために使うそうです。つまり、定期的に接続して切られないようにしている感じです。
クエリの実行
次にカーソルオブジェクトを作成します。カーソルというのは、データベースで使われる用語のようです。詳しくは知らないので、ここでは、クエリの実行と結果を受け取るために必要な DB への命令方法だと思えば問題ないと思います。
cur = conn.cursor() cur.execute('select * from member') table = cur.fetchall() print(table)
conn.cursor()
で、カーソルオブジェクトを作成し、cur.execute()
で文字列をクエリとして DB に送ります。その結果を cur.fetchall()
で受け取り、print()
出力しています。
ちなみに cur.fetchall()
は、例えば SELECT の結果を全て受け取りますが、 cur.fetchone()
は結果を一つだけ受け取ります。fetchone()
は、何度も実行することで続きのデータを受け取ることができます。
例として、SELECT * FROM Table;
というクエリを実行して、レコードが 3 つ現れるとします。fetchall()
の場合は、この結果を全て受け取りますが、fetchone()
では、レコードを 1 つだけ受け取ります。全て受け取る場合は、3 回実行する必要があるわけです。
それぞれにメリット、デメリットがあるようですがここでは説明しません(というか知りません……)。ちなみに、レコードを全て受け取った状態で fetchone()
を print()
で出力すると None と出力されるので、 for 文などで簡単に回せそうです。
以上が簡単な MySQL データベースへの接続方法です。重要なのは、 mysql.connector.connect()
, connect.cursor()
, cursor.execute()
, cursor.fetchall()
ですかね。
最後に一通り実行できるコードを載せておきます。
# -*- coding: utf-8 -*- import mysql.connector conn = mysql.connector.connect( host = 'localhost', port = 3306, user = 'root', password = 'pass', database = 'test', ) connected = conn.is_connected() print(connected) if(not connected): conn.ping(True) cur = conn.cursor() cur.execute('SELECT * FROM member') # table = cur.fetchall() # print(table) print(cur.statement) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone()) print(cur.fetchone())
参考
今回出てきた API のドキュメントを載せておきます。
MySQL :: MySQL Connector/Python Developer Guide :: 7.1 Connector/Python Connection Arguments
MySQL :: MySQL Connector/Python Developer Guide :: 10.2.25 MySQLConnection.is_connected() Method
MySQL :: MySQL Connector/Python Developer Guide :: 10.2.27 MySQLConnection.ping() Method
googletest を使ってみた
北海道の土産用お菓子は、どれもおいしくて最高です。
趣味でコードを書いてるけど、テストコードは全く書いてこず、仕事でテストコードを初めて書いて、良いテストコードを書くのは難しいなぁと実感し、ちょっとこれは練習しないとダメだなということで、テストコードを書く環境を作り始めました。
googletest
を見つけたので、これでいいかと選択。使う理由は、情報が多そうなのと使いやすそうな感じが理由。
Windows
版の Visual Studio 2017
上で動かしたので、そのまとめを書いておきます。
googletest を落とす
まずは、googletest を落としてこないと始まりません。
落としたら解凍します。
Google Test を追加
google-master/googletest/msvc/2010/
の中に、gtest.sln
というソリューションファイルがあるので、Visual Studio で開きます。
開くと、セキュリティ警告をしてくると思うので、内容を読んで、問題なければ OK を押します。そのあとプロジェクトの再ターゲットが出るので、設定に問題なければ OK を押します。
完了したら gtest.sln を閉じます。次にテスト対象のプロジェクトを用意します。今回は、TestProject
というプロジェクトを作成しました。次に、ソリューションに googletest
のプロジェクトを追加します。
ソリューションエクスプローラ
からソリューション
を右クリックし、追加 > 既存のプロジェクト
を選び、
先ほど解凍した googletest/msvc/2010/gtest.vcxproj
を追加します。追加すると以下のようになります。
環境設定
TestProject
には、何もコードが書かれていないので追加します。ここでは、main.cpp
を追加しました。追加したら、まずは googletest
を使えるようにしましょう。TestProject
のプロパティ
を開き、構成プロパティ > C/C++ > 全般
のなかの追加のインクルードディレクトリ
に新しいパスを追加します。
そこに googletest/include
を追加します。もちろん、googletest より前は、googletest を置いている場所のパスが入ります。追加したら OK をクリックし、設定を反映させます。次に、TestProject
の参照を追加します。参照
を右クリックすると参照の追加
が出るので、それをクリックし、gtest
にチェックを入れます。
最後に、gtest プロジェクトのプロパティを表示し、構成プロパティ > C/C++ > コード生成
からランタイムライブラリ
を環境に合わせて設定します。よく分からない場合は、テスト対象のプロジェクトと同じにすれば問題ないはずです。ここでは、構成
を Debug
に変更し、ランタイムライブラリ
をマルチスレッドデバッグDLL(/MDd)
にしました。OK をクリックして、プロパティを閉じます。
テストコードの作成
最後にテストコードを作成します。今回は、main.cpp
に直接テストコードを作成します。
#include "gtest\gtest.h" TEST() { EXPECT_EQ(0, 1 - 1); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
main
関数内の ::testing::InitGoogleTest(&argc, argv)
と RUN_ALL_TEST()
がテスト実行のために必要な処理です。TEST(){}
内の処理が実際にテストしたい内容になります。
これを実行すると以下のように表示されます。
以上で基本的な設定と使い方は、完了です。 詳しく知りたい方は、
入門ガイド — Google Test ドキュメント日本語訳
あたりを参照するといいでしょう。
おまけ
googletest は、include ディレクトリと msvc ディレクトリ、src ディレクトリが同じ階層にあれば問題なさそうなので、この三つをコピーして、ソリューションごとに置くと良さそうです。
おわり
以上が googletest の使い方でした。Visual Studio に googletest を入れていると Visual Studio さんに Test Adapter for Google Test をお勧めされたので、気が向いたら試してみようと思います。Community でも使えるんですかね……?
JSON for Modern C++ を使ってみたメモ
メモ書き
JSON for Modern C++ とは?
以下、参照。
使い方
Github のページの json/src/
に json.hpp
というファイルがあるので、これを include
する。
#include "json.hpp" using json = nlohmann::json;
この json
クラスを使って、JSON ファイルを読んだり書いたりする。
以下のような JSON ファイルを使って、例を示していく。
ファイル名は、test.json
として進めていく。
{ "pi": 3.141, "happy": true, "name": "Niels", "nothing": null, "answer": { "everything": 42 }, "list": [1, 0, 2], "object": { "currency": "USD", "value": 42.99 } }
JSON ファイルの読み込み
JSON ファイルを読む必要があるので、まずはファイルを読む。
std::ifstream reading("test.json", std::ios::in);
ファイルの入出力は以下を参照。
ファイルを読んだら以下のようにして取り出す。
json j; reading >> j;
これだけで、ファイルの中身がすべて json j
に入っている。
試しに以下のように出力すると
reading >> j; std::cout << j << std::endl;
以下のように出力される。
{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}
改行はしてくれないっぽい。
このデータだけ取り出したいってときは、以下のようにする。
std::cout << j["pi"] << std::endl; // 出力結果は、3.141
begin(), end() を使って取り出すことができる。
std::for_each(j.begin(), j.end(), [](auto it) {
std::cout << it << std::endl;
});
結果は、以下のようなる。
{"everything":42} true [1,0,2] "Niels" null {"currency":"USD","value":42.99} 3.141
begin, end を使うとアルファベット順になる。
C++17 だと以下のように書ける。
for (auto& elem : j) { std::cout << elem << std::endl; }
JSON ファイルへ書き込み
未調査…
おわり
とても使いやすい。まだまだ調べ切れていないので、分かり次第更新していく予定。