web-dev-qa-db-fra.com

Comment passer des arguments à la fonction principale dans le module Python?

J'ai récemment commencé à en savoir plus sur Python Packages et modules. Je suis actuellement occupé à mettre à jour mes modules existants afin qu'ils puissent être exécutés en tant que script ou importés en tant que module dans mon autre code. I ' Je ne sais pas comment construire mes arguments d'entrée dans mon module et les transmettre à la fonction main () de mon module.

J'ai écrit ma fonction main () et je l'ai appelée sous si __name__ == '__main __' en passant les arguments d'entrée. Les entrées sont actuellement codées en dur pour montrer ce que j'essaie de réaliser. Toute aide sur la façon de construire correctement mes arguments d'entrée que l'utilisateur passera, qui seront ensuite passés à la fonction principale sera appréciée.

Comme mentionné, j'essaie de pouvoir utiliser ce qui suit comme script lorsqu'il est utilisé directement ou importé en tant que module dans mon autre code et exécuté à partir de là. Si je l'importe en tant que module, est-ce que j'appelle la fonction main () lors de son importation? La structure suivante est-elle correcte dans la façon dont j'ai écrit ce qui suit? Tout conseil est apprécié.

'''
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")

Mis à jour: 17/03/13

Ce qui suit est mon module Python basé sur les suggestions de Jonathan:

'''
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

Cela me semble correct, et oui si vous cherchez à l'utiliser comme module, vous importeriez main. Cependant, il serait probablement préférable de le nommer d'une manière plus descriptive.

Pour clarifier le fonctionnement de __main__ Et de la fonction main(). Lorsque vous exécutez un module, il aura un nom qui est stocké dans __name__. Si vous exécutez le module seul en tant que script, il aura le nom __main__. Si vous l'exécutez dans le cadre d'un module, c'est-à-dire que vous l'importez dans un autre module, il aura le nom du module.

La fonction main() peut être nommée comme vous le souhaitez et cela n'affectera pas votre programme. Il est communément appelé main dans les petits scripts, mais ce n'est pas un nom particulièrement bon s'il fait partie d'un corps de code plus large.

En termes permettant à un utilisateur de saisir des arguments lors de l'exécution en tant que script, je chercherais à utiliser argparse ou click

Un exemple de la façon dont argparse fonctionnerait.

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