# モジュール ## モジュール 1つのファイルに記述していると、プログラムが長くなるとどこに何を書いているのかがわからなくなってきます。 処理が長く、複雑になると、複数のファイルに処理を分割する必要があります。役割ごとにファイルを分割することで、それぞれどういった処理をするものかを明確にできます。 Pythonでは他のPythonファイルや関数をインポート(import)して再利用できます。処理を複数のファイルに分割し、必要な処理をインポートして使います。 実行環境直下に `calc.py` というファイルを作成して、 `add()` 、 `sub()` 関数を定義しましょう({numref}`calc-py`)。 (calc-py)= ```{code-block} python :caption: "add()、sub()関数の定義(calc.py)" def add(a, b): return a + b def sub(a, b): return a - b ``` ```{index} import single: Module; import ``` 別のファイルをインポートするには `import` 文を使います。 Pythonインタープリタを起動して、 `calc.py` をインポートしましょう({numref}`import-calc`)。 (import-calc)= ```{code-block} pycon :caption: "calcのインポート" import calc ``` `calc` というモジュールがインポートされました。 Pythonファイルをインポートすることでモジュール(module)として再利用できます。 `calc` モジュールから `add()` 関数を使うには、 `calc.add()` と呼び出します({numref}`call-calc-add`)。 (call-calc-add)= ```{code-block} pycon :caption: "別モジュールの関数を利用" calc.add(1, 2) 3 ``` ```{index} from single: Module; from ``` ### 関数のインポート `add()` 関数を直接インポートするには、 `from <モジュール> import <インポート対象>` 文を使います。 `from <モジュール>` の部分にモジュール、 `import <インポート対象>` の部分にインポートの対象を書きます({numref}`import-function`)。 (import-function)= ```{code-block} pycon :caption: "関数のインポート" from calc import add add(1, 2) 3 ``` ```{index} as single: Module; as ``` ### 別名をつける インポートした関数やモジュールに別名をつけるには `as` を使います。 関数やモジュールが頻繁に使われるのに名前が長い場合に使われます。 `import <インポート対象> as <別名>` のように別名を指定します。 `calc` モジュールに別名 `c` をつけてインポートするには {numref}`import-as` のようにします。 (import-as)= ```{code-block} pycon :caption: "インポート対象に別名をつける" import calc as c c.add(1, 2) 3 ``` ### 複数の対象をインポート `calc` モジュールから `add()` 、 `sub()` 関数を一度にインポートするには、 `import` 文でインポート対象をカンマ区切りで指定します({numref}`import-functions`)。 (import-functions)= ```{code-block} pycon :caption: "複数の対象をインポート" from calc import add, sub add(1, 2) 3 sub(2, 1) 1 ``` また、 {numref}`import-functions2` のように括弧を使っても指定できます。 インポート対象が多い場合は括弧を使った書き方のほうが可読性が高いので、こちらを使います。 (import-functions2)= ```{code-block} pycon :caption: "括弧を使った複数のインポート" from calc import ( ... add, ... sub, ... ) ``` ```{index} Standard library ``` ## 標準ライブラリの利用 Python自体も標準でモジュールを提供しています。これら標準で提供されているモジュールをまとめて標準ライブラリと呼びます。 必要な処理をすべて自分で実装するのでなく、積極的に標準ライブラリを利用しましょう。 標準ライブラリを利用すると重複する実装が減り、コードの記述量を大幅に削減できます。 ```{index} datetime single: Standard library; datetime ``` ### 日付を扱うモジュール 標準ライブラリの1つ `datetime` モジュールを取り上げます。 `datetime` は日付や時刻を簡単に扱うことができるモジュールです。 ここでは例として日付の計算をします。 `datetime.date()` コンストラクタを使って日付を意味するオブジェクトを生成できます。 引数として年、月、日を指定します。 ```{code-block} pycon :caption: "datetime.date()コンストラクタ" import datetime d = datetime.date(2016, 12, 23) print(d.year, d.month, d.day) 2016 12 23 ``` また、 `datetime.date.today()` メソッドを使うと今日の日付を取得することができます。 ```{code-block} pycon :caption: "datetime.date.today()メソッド" today = datetime.date.today() print(today) # 実行する日によって結果が異なる 2018-02-17 ``` ここで、自分が生まれてから今日までに何日経過したのかを計算してみましょう。 自分で実装しようとすると、月ごとに日数が違う、うるう年の計算など面倒な計算が必要となりますが、 `datetime.date` を使うと面倒な部分をモジュールが肩代わりしてくれます。 ```{code-block} pycon :caption: "datetime.date.today()メソッド" birthday = datetime.date(2008, 12, 3) # Python 3.0のリリース日 today = datetime.date.today() delta = today - birthday # 日付や時刻の差を表すdatetime.timedeltaオブジェクト print(delta.days) # 実行する日によって結果が異なる 3363 ``` `datetime` モジュールは他にも時刻を扱う `datetime.time`, 日付と時刻両方を扱う `datetime.datetime` など日付や時刻の計算に便利な関数がたくさんあります。 詳しくはPythonの公式ドキュメントの「 [datetimeモジュール](https://docs.python.org/ja/3/library/datetime.html) 」を参考にしてください。 ```{index} re single: Standard library; re ``` ### 正規表現モジュール 次に標準ライブラリの1つ `re` モジュールを扱います。 `re` モジュールはPythonで正規表現を扱うためのモジュールです。 `re.search()` 関数を使って、文字列が正規表現にマッチするか調べられます。第1引数に正規表現、第2引数に対象の文字列を渡します({numref}`re-module`)。 (re-module)= ```{code-block} pycon :caption: "reモジュールの利用" import re m = re.search('(P(yth|l)|Z)o[pn]e?', 'Python') m ``` 正規表現にマッチした場合、 `re.search()` は結果を表すマッチオブジェクトを返します。 マッチオブジェクトから値を取り出すには、 `.group()` メソッドを呼び出します({numref}`match-object`)。 (match-object)= ```{code-block} pycon :caption: "正規表現にマッチした文字列の取得" m.group() 'Python' ``` 正規表現がグループを含む場合、グループの番号を引数に渡して取り出せます。 引数を指定しないか、0を指定すると、正規表現全体のマッチが返されます({numref}`match-group`)。 (match-group)= ```{code-block} pycon :caption: "グループを指定して文字列の取得" m = re.search('py(thon)', 'python') m.group() 'python' m.group(0) 'python' m.group(1) 'thon' ``` 正規表現にマッチしない場合は、{numref}`not-match` に示すように何も返しません(`None` を返します)。 (not-match)= ```{code-block} pycon :caption: "正規表現にマッチしない場合" re.search('py', 'ruby') ``` ```{admonition} コラム: 正規表現の文字列 正規表現の文字列にはPythonのraw文字列を使うのが一般的です。 `r` プレフィックスをつけてraw文字列を定義します。 raw文字列ではバックスラッシュを特別扱いしないので、 正規表現中にバックスラッシュを使う際に `'\\'` と書く必要がなくなります。 ``` `re` モジュールには、ここで説明していない有効な使い方があります。 Pythonの公式ドキュメントの「 [reモジュール](https://docs.python.org/ja/3/library/re.html) 」を参考にしてください。 また、他のPython標準ライブラリについては、「 [Python標準ライブラリ](https://docs.python.org/ja/3/library/index.html) 」を参考にしてください。 ----- ## サードパーティ製パッケージ Python は標準ライブラリだけでもいろいろなことができますが、さらに便利なサードパーティ製のパッケージも提供されています。 サードパーティ製パッケージは [PyPI](https://pypi.org/) (the Python Package Index、パイピーアイと読む)というサイトで情報が共有されています。 ```{figure} images/pypi.png :alt: PyPI - the Python Package Index :width: 600 PyPI - the Python Package Index ``` ### pipコマンド サードパーティ製パッケージをインストールするには、 **pipコマンド** を使用します。 **以下はpipコマンドのサンプルです** ここでは実行しないで、以下のvenv環境を作ってから実行しましょう。 pip コマンドを利用すると以下の様なコマンドで簡単にサードパーティ製パッケージをインストールできます。 ```{index} requests single: pip; requests ``` ```{code-block} sh :caption: "pipコマンドで (パッケージ名) をインストール" $ pip install パッケージ名 ``` ````{admonition} コラム: pip自身のアップグレード pip自身もpipコマンドでアップグレードを行えます。 アップグレードは、次のコマンドを実行します。 ```{code-block} sh :caption: "pipをアップグレード(macOS、Linux)" $ pip install pip --upgrade ``` Windowsの場合、このコマンドを実行すると現在入っているpipが削除されたうえに最新バージョンのpipのインストールに失敗してpipが使えなくなることがたまに発生します。以下のコマンドを使ってください。 ```{code-block} sh :caption: "pipをアップグレード(Windows)" > python -m pip install --upgrade pip ``` ```` `pip freeze` コマンドを実行すると、インストールしたパッケージの一覧が出力されます。 ```{code-block} sh :caption: pip freeze コマンドでパッケージの情報を書き出す (env) $ pip install requests (env) $ pip freeze > requirements.txt (env) $ cat requirements.txt certifi==2017.4.17 chardet==3.0.4 idna==2.5 requests==2.18.1 urllib3==1.21.1 ```