GIS奮闘記

現役GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

Pythonで作ったモジュールのパッケージ化をしてみよう

GISはあまり関係なくPython一般のお話になってしまうのですが、本日はPythonでのパッケージ化について書いてみようと思います。

このブログを読んでくださっている方の中でPython経験者は多数いらっしゃるかと思います。ただ、以下のような理由でパッケージ化をしたことがないという方も一定数いらっしゃるのではと思っています。

  1. パッケージ化するほどの大きなプログラムを書く必要がない
  2. パッケージ化しなくてもやりたいことができるので覚える必要がない
  3. そもそもパッケージ化できることを知らなかった
  4. etc

たしかに、開発するプログラムが小規模の場合、パッケージ化の効果は少ないかもしれませんが、大規模化して同じメソッドやクラスを再利用する回数が増えると、パッケージ化の効果は大きくなります。もし、将来的に大規模開発を行う、もしくは、行いたいという場合は覚えていておいて損はないかと思います。

パッケージの作成

以下のようなディレクトリを作ってみました。
f:id:sanvarie:20190629135525p:plain

main.pyが今回メインとなる処理のファイルですね。

libフォルダの中身はこのようになっています。
f:id:sanvarie:20190629134926p:plain

featureclass.pyがmain.pyでインポートされるモジュールです。

パッケージの初期化ファイル (__init.py__)

もう一つ、__init__.pyというのがあるのですが、これは空のファイルです。Python 3.3 より前のバージョンでは、パッケージディレクトリに __init__.py というファイルを置かなければ、そのディレクトリをパッケージとして認識させることができませんでした(ImportError: No module named ... というエラーが発生する)。Python 3.3 より前のバージョンをお使いの方は__init__.pyを必ず作成してください。

全体の構成はこのようになります。
f:id:sanvarie:20190629140958p:plain

モジュールのインポート

featureclass.pyのインポートをする前にfeatureclass.pyでどのような処理をしているのかを解説します。一応GISがメインのブログなのでArcPyを使用したプログラムにしてみました。

featureclass.py
# -*- coding: utf-8 -*-
import arcpy

class FeatureClass():

    def __init__(self):
        pass

    def get_shape_type(self, fc):
        """対象フィーチャクラスのshapeTypeを取得します。
           アノテーションのFeatureTypeはPolygon→Annotationに変換します

        arguments:
            fc -- フィーチャクラス名

        returns:
            geo_type -- ジオメトリタイプ
        """

        fc_type = arcpy.Describe(fc).FeatureType

        #アノテーションのジオメトリタイプはポリゴンになってしまうのでこの処理を追加
        if fc_type == "Annotation":

            geo_type = "Annotation"

        else:

            geo_type = arcpy.Describe(fc).shapeType

        return geo_type

get_shape_typeというメソッドのみ実装したシンプルなクラスですね。このメソッドは引数として受け取ったフィーチャクラス名からそのフィーチャクラスのジオメトリタイプをreturnします。これをmain.pyで呼び出すとこのようになります。

main.py
# -*- coding: utf-8 -*-
import arcpy
from lib.featureclass import FeatureClass

class Main():

    def __init__(self):
        pass

    def main(self):
        arcpy.env.workspace = r"D:\python\data\Sample.gdb"
        featureclass = FeatureClass()

        # ワークスペースのフィーチャクラスのジオメトリタイプを取得
        for f in arcpy.ListFeatureClasses():
            print(featureclass.get_shape_type(f))

if __name__ == '__main__':
    m = Main()
    m.main()

ポイントとしては以下3点です。

  1. from lib.featureclass import FeatureClassでモジュールをインポート
  2. featureclass = FeatureClass()でインスタンス化
  3. 作成したインスタンスでget_shape_typeを実行

Sample.gdbにあるフィーチャクラス分ループを行い、get_shape_typeで取得したジオメトリタイプをprintするという処理です。使用したデータは以下のフィーチャクラスです。

f:id:sanvarie:20190629141206p:plain

実行結果はこのようになりました。
f:id:sanvarie:20190629141636p:plain

これだけです。とても簡単ですね。これをすることで共通的な処理などをパッケージ化して作業の効率化などを図ることができるかと思います。また、少しハードルが上がるのですが、PYPIに作成したパッケージを登録することもできるかと思います。夢が広がりますね。

pypi.org

本日は以上です。