web-dev-qa-db-ja.com

Pythonモジュール内でメイン関数に引数を渡す方法は?

最近、Pythonパッケージとモジュールについての詳細を学び始めました。現在、既存のモジュールをスクリプトとして実行したり、モジュールとして他のコードにインポートできるように更新しています。 mモジュール内で入力引数を作成し、それらをモジュール内のmain()関数に渡す方法がわからない。

main()関数を作成し、if __name__ == '__main __'で入力引数を渡して呼び出しました。入力は現在、私が達成しようとしていることを示すためにハードコードされています。ユーザーが渡す入力引数を正しく作成する方法についてのヘルプは、メイン関数に渡されます。

前述のように、直接使用するか、モジュールとして他のコードにインポートしてそこから実行すると、スクリプトとして次のものを使用できるようにしようとしています。モジュールとしてインポートする場合、インポート時にmain()関数を呼び出しますか?次の構造は、私が以下を書いた方法で正しいですか?どんなアドバイスも大歓迎です。

'''
Created on March 12, 2017

Create a new ArcHydro Schema

File Geodatabase and Rasters

Folder

@author: PeterW
'''
# import site-packages and modules
import re
from pathlib import Path
import arcpy

# set environment settings
arcpy.env.overwriteOutput = True


def archydro_rasters_folder(workspace):
    """Create rasters folder directory
    if it doens't already exist"""
    model_name = Path(workspace).name
    layers_name = re.sub(r"\D+", "Layers", model_name)
    layers_folder = Path(workspace, layers_name)
    if layers_folder.exists():
        arcpy.AddMessage("Rasters folder: {0} exists".format(layers_name))
    else:
        layers_folder.mkdir(parents=True)
        arcpy.AddMessage("Rasters folder {0} created".format(layers_name))


def archydro_fgdb_schema(workspace, schema, dem):
    """Create file geodatabase using XML
    schema and set coordinate system based
    on input DEM if it doesn't already exist"""
    model_name = Path(workspace).name
    fgdb = "{0}.gdb".format(model_name)
    if arcpy.Exists(str(Path(workspace, fgdb))):
        arcpy.AddMessage("{0} file geodatabase exists".format(fgdb))
    else:
        new_fgdb = arcpy.CreateFileGDB_management(str(workspace), fgdb)
        import_type = "SCHEMA_ONLY"
        config_keyword = "DEFAULTS"
        arcpy.AddMessage("New {0} file geodatabase created".format(fgdb))
        arcpy.ImportXMLWorkspaceDocument_management(new_fgdb, schema,
                                                    import_type,
                                                    config_keyword)
        arcpy.AddMessage("ArcHydro schema imported")
        projection = arcpy.Describe(dem).spatialReference
        projection_name = projection.PCSName
        feature_dataset = Path(workspace, fgdb, "Layers")
        arcpy.DefineProjection_management(str(feature_dataset),
                                          projection)
        arcpy.AddMessage("Changed projection to {0}".format(projection_name))


def main(workspace, dem, schema):
    """main function to create rasters folder
    and file geodatabase"""
    archydro_rasters_folder(workspace)
    archydro_fgdb_schema(schema, dem, workspace)

if __name__ == '__main__':
    main(workspace = r"E:\Projects\2016\01_Bertrand_Small_Projects\G113268\ArcHydro\Model04",
         dem = r"E:\Projects\2016\01_Bertrand_Small_Projects\G113268\ArcHydro\DEM2\raw",
         schema = r"E:\Python\Masters\Schema\ESRI_UC12\ModelBuilder\Schema\Model01.xml")

更新済み:17/03/13

以下は、Jonathanの提案に基づいて更新されたPythonモジュールです。

'''
Created on March 12, 2017

Create a new ArcHydro Schema

File Geodatabase and Rasters

Folder

@author: PeterW
'''
# import site-packages and modules
import re
from pathlib import Path
import arcpy
import argparse

# set environment settings
arcpy.env.overwriteOutput = True


def rasters_directory(workspace):
    """Create rasters folder directory
    if it doens't already exist"""
    model_name = Path(workspace).name
    layers_name = re.sub(r"\D+", "Layers", model_name)
    layers_folder = Path(workspace, layers_name)
    if layers_folder.exists():
        arcpy.AddMessage("Rasters folder: {0} exists".format(layers_name))
    else:
        layers_folder.mkdir(parents=True)
        arcpy.AddMessage("Rasters folder {0} created".format(layers_name))


def fgdb_schema(workspace, schema, dem):
    """Create file geodatabase using XML
    schema and set coordinate system based
    on input DEM if it doesn't already exist"""
    model_name = Path(workspace).name
    fgdb = "{0}.gdb".format(model_name)
    if arcpy.Exists(str(Path(workspace, fgdb))):
        arcpy.AddMessage("{0} file geodatabase exists".format(fgdb))
    else:
        new_fgdb = arcpy.CreateFileGDB_management(str(workspace), fgdb)
        import_type = "SCHEMA_ONLY"
        config_keyword = "DEFAULTS"
        arcpy.AddMessage("New {0} file geodatabase created".format(fgdb))
        arcpy.ImportXMLWorkspaceDocument_management(new_fgdb, schema,
                                                    import_type,
                                                    config_keyword)
        arcpy.AddMessage("ArcHydro schema imported")
        projection = arcpy.Describe(dem).spatialReference
        projection_name = projection.PCSName
        feature_dataset = Path(workspace, fgdb, "Layers")
        arcpy.DefineProjection_management(str(feature_dataset),
                                          projection)
        arcpy.AddMessage("Changed projection to {0}".format(projection_name))


def model_schema(workspace, schema, dem):
    """Create model schema: rasters folder
    and file geodatabase"""
    rasters_directory(workspace)
    fgdb_schema(schema, dem, workspace)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Create a ArcHydro schema')
    parser.add_argument('--workspace', metavar='path', required=True,
                        help='the path to workspace')
    parser.add_argument('--schema', metavar='path', required=True,
                        help='path to schema')
    parser.add_argument('--dem', metavar='path', required=True,
                        help='path to dem')
    args = parser.parse_args()
    model_schema(workspace=args.workspace, schema=args.schema, dem=args.dem)
9
Peter Wilson

これは私には正しいように見えますが、これをmainとしてインポートするモジュールとして使用する場合は、そうです。ただし、よりわかりやすい名前を付ける方が良いでしょう。

___main___と関数main()がどのように機能するかを明確にするため。モジュールを実行すると、___name___に保存されている名前になります。モジュールをスクリプトとしてスタンドアロンで実行すると、___main___という名前になります。モジュールの一部として実行する場合、つまり別のモジュールにインポートする場合、モジュールの名前が付けられます。

関数main()には任意の名前を付けることができ、プログラムに影響はありません。通常、小さなスクリプトではmainと名付けられますが、より大きなコード本体の一部である場合は特に良い名前ではありません。

スクリプトとして実行するときにユーザーが引数を入力できるようにするには、 argparse または click を使用して調べます。

Argparseの動作例。

_if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='Create a ArcHydro schema')
    parser.add_argument('--workspace', metavar='path', required=True,
                        help='the path to workspace')
    parser.add_argument('--schema', metavar='path', required=True,
                        help='path to schema')
    parser.add_argument('--dem', metavar='path', required=True,
                        help='path to dem')
    args = parser.parse_args()
    main(workspace=args.workspace, schema=args.schema, dem=args.dem)
_
12
Jonathan