如何将参数传递给 Python 模块中的 main 函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42747469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 22:06:14  来源:igfitidea点击:

How to pass arguments to main function within Python module?

pythonmoduleargumentspackages

提问by Peter Wilson

I have recently started learning more about Python Packages and Modules. I'm currently busy updating my existing modules so that that can be run as script or imported as a module into my other code. I'm not sure how to construct my input arguments within my module and pass them to the main() function within my module.

我最近开始学习更多关于 Python 包和模块的知识。我目前正忙于更新我现有的模块,以便它可以作为脚本运行或作为模块导入到我的其他代码中。我不确定如何在我的模块中构造我的输入参数并将它们传递给我的模块中的 main() 函数。

I've have written my my main()function and called it under if __name__ == '__main__'passing the input arguments. The inputs are currently hard coded to show what I'm trying to achieve. Any help in how to correctly construct my input arguments that the user will pass, which will then be passed onto the main function will be appreciated.

我已经编写了我的main()函数并在if __name__ == '__main__'传递输入参数下调用它。输入目前是硬编码的,以显示我想要实现的目标。任何有关如何正确构造用户将传递的输入参数的帮助,然后将其传递给主函数将不胜感激。

As mentioned I'm trying to be able to use the following as a script when used directly or imported as a module into my other code and run from there. If I import it as a module would I call the main()function when importing it? Is the following structure correct in how I have written the following? Any advice is appreciated.

如前所述,当直接使用或作为模块导入到我的其他代码中并从那里运行时,我试图能够将以下内容用作脚本。如果我将它作为模块导入,我会在导入时调用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:\Projects16_Bertrand_Small_Projects\G113268\ArcHydro\Model04",
         dem = r"E:\Projects16_Bertrand_Small_Projects\G113268\ArcHydro\DEM2\raw",
         schema = r"E:\Python\Masters\Schema\ESRI_UC12\ModelBuilder\Schema\Model01.xml")

Updated: 17/03/13

更新:17/03/13

The following is my updated Python module based on Jonathan's suggestions:

以下是我根据 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)

回答by Jonathan

This looks correct to me, and yes if you're looking to use this as a module you would import main. Though, it would probably be better to name it in a more descriptive way.

这对我来说看起来是正确的,是的,如果您想将它用作模块,您将导入 main。不过,以更具描述性的方式命名它可能会更好。

To clarify how __main__and the function main()works. When you execute a module it will have a name which is stored in __name__. If you execute the module stand alone as a script it will have the name __main__. If you execute it as part of a module ie import it into another module it will have the name of the module.

阐明__main__功能的main()工作方式和工作原理。当您执行一个模块时,它将有一个名称存储在__name__. 如果您将模块作为脚本独立执行,它将具有名称__main__. 如果您将它作为模块的一部分执行,即将它导入另一个模块,它将具有模块的名称。

The function main()can be named anything you would like, and that wouldn't affect your program. It's commonly named mainin small scripts but it's not a particularly good name if it's part of a larger body of code.

该函数main()可以任意命名,这不会影响您的程序。它通常main在小脚本中命名,但如果它是较大代码体的一部分,则它不是一个特别好的名字。

In terms letting a user to input arguments when running as a script I would look into either using argparseor click

在让用户在作为脚本运行时输入参数方面,我会研究使用argparseclick

An example of how argparse would work.

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)