29

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.

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.

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.

'''
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:\Projects2016円01円_Bertrand_Small_Projects\G113268\ArcHydro\Model04",
 dem = r"E:\Projects2016円01円_Bertrand_Small_Projects\G113268\ArcHydro\DEM2\raw",
 schema = r"E:\Python\Masters\Schema\ESRI_UC12\ModelBuilder\Schema\Model01.xml")

Updated: 17/03/13

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

'''
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)
asked Mar 12, 2017 at 12:39

1 Answer 1

36

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.

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.

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

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

An example of how argparse would work.

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)
answered Mar 12, 2017 at 13:01
Sign up to request clarification or add additional context in comments.

9 Comments

Hi Jonathan, thanks for the following. So my main() function doesn't have to be called main?
nope, you can call it whatever you like. I updated the answer to include some more detail :)
Hi Jonathan, would you be able to give me an example how to pass the arguments using argparse to my main() funciton. The reason for asking is that I call two functions within my main() func that use the argument workspace.
I've updated the answer to include how to use argparse.
Hi Jonathan, I can't thank you enough, you have been a great help. The following is going to nelp me a lot with my code going forward.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.