杰瑞科技汇

ArcGIS Python样式如何自动化制图?

Of course! "ArcGIS Python style" isn't about a single, rigid set of rules, but rather a collection of best practices and conventions for writing clean, efficient, and maintainable Python code specifically for use with ArcGIS.

ArcGIS Python样式如何自动化制图?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the key aspects of ArcGIS Python style, broken down into logical sections.


The Golden Rule: Readability is Paramount

The primary goal of any style guide is to make code easy for humans to read and understand. This is especially true in GIS, where projects can be complex, long-lived, and involve collaboration. A consistent style helps you and your colleagues quickly grasp what a script does, how it works, and how to modify it.


Naming Conventions (How to Name Things)

Consistent naming reduces confusion and makes your code self-documenting.

Variables and Functions (camelCase or snake_case)

Use snake_case for variables and functions. This is the most common and readable convention in Python.

ArcGIS Python样式如何自动化制图?-图1
(图片来源网络,侵删)
  • Good:

    input_feature_class = r"C:\Data\Parcels.shp"
    output_feature_class = r"C:\Data\Parcels_Projected.shp"
    def calculate_area(fc_path):
        # ... function logic
        pass
  • Avoid (PascalCase):

    InputFeatureClass = r"C:\Data\Parcels.shp" # PascalCase is for classes

Classes (PascalCase)

Use PascalCase (also known as CamelCase) for class names. This is a standard Python convention.

  • Good:

    ArcGIS Python样式如何自动化制图?-图3
    (图片来源网络,侵删)
    class ParcelAnalyzer:
        def __init__(self, feature_class):
            self.fc = feature_class
        def calculate_areas(self):
            # ... method logic
            pass

Constants (UPPER_SNAKE_CASE)

Use UPPER_SNAKE_CASE for constants—values that should never change.

  • Good:
    BUFFER_DISTANCE = 100  # in meters
    WORKSPACE = r"C:\Data\MyProject.gdb"

Geodatabase and File Names

Keep these simple and descriptive. Use underscores (_) instead of spaces.

  • Good: parcels_analysis.gdb, 2025_Infrastructure_Project.gdb, city_roads.shp
  • Avoid: Parcels Analysis.gdb, City Roads.shp

Code Structure and Formatting

Indentation: Use 4 Spaces

Always use 4 spaces for indentation. Do not use tabs, as they can display differently across different text editors and cause errors.

  • Good:
    for row in arcpy.da.SearchCursor(fc, ["SHAPE@"]):
        # 4 spaces for the loop block
        area = row[0].getArea("GEODESIC")
        if area > 10000:
            # 8 spaces for the if block
            print("Large parcel found.")

Line Length: Max 79 or 99 Characters

To ensure readability across different screens and editors, limit lines to 79 characters. For code that will be printed or viewed in a console, 99 characters is a common and acceptable alternative.

  • Bad (too long):
    arcpy.management.SelectLayerByAttribute(lyr, "NEW_SELECTION", f"\"OWNER_NAME\" = '{some_very_long_owner_name_from_a_database_field}' AND \"PARCEL_ID\" IS NOT NULL")
  • Good (using parentheses for implicit line continuation):
    arcpy.management.SelectLayerByAttribute(
        lyr, 
        "NEW_SELECTION", 
        f"\"OWNER_NAME\" = '{some_very_long_owner_name_from_a_database_field}' "
        f"AND \"PARCEL_ID\" IS NOT NULL"
    )

Whitespace

Use whitespace to improve readability around operators and after commas.

  • Good:

    # Around operators
    result = (a + b) * c
    # After commas
    fields = ["OID@", "SHAPE@", "LAND_USE"]

Writing Idiomatic ArcGIS Python Code

This is where ArcGIS-specific best practices come into play.

Import Statements

  • Group imports: Standard library, third-party libraries, and local application imports.

  • Use arcpy as an alias: This is the universal standard.

  • Import specific functions when possible: This can make code clearer and slightly more efficient.

  • Good:

    # Standard library
    import os
    import datetime
    # Third-party library
    import pandas as pd
    # ArcGIS module
    import arcpy
    # Specific function from a module
    from arcpy import env
    # Specific function from a toolset
    from arcpy.management import CreateFeatureclass, AddField

Workspace Management (Crucial!)

Always set the workspace environment. This simplifies paths for many tools.

  • Good:

    import arcpy
    # Define your workspace path once
    gdb_path = r"C:\Data\MyProject.gdb"
    arcpy.env.workspace = gdb_path
    # Now you can just use the name of the dataset
    arcpy.management.CopyFeatures("Parcels", "Parcels_Backup")

Using arcpy.da Cursors (Modern & Fast)

For iterating through features or tables, always use the arcpy.da module (SearchCursor, UpdateCursor, InsertCursor). It is significantly faster and more memory-efficient than the older arcpy cursors.

  • Good:

    import arcpy
    fc = "Parcels"
    fields = ["OID@", "SHAPE@AREA"]
    with arcpy.da.SearchCursor(fc, fields) as cursor:
        for row in cursor:
            oid = row[0]
            area = row[1]
            print(f"Object ID: {oid}, Area: {area:.2f}")
  • Avoid (Older, slower method):

    # Don't do this unless you have a specific reason
    rows = arcpy.SearchCursor(fc, fields)
    for row in rows:
        oid = row.getValue("OID@")
        area = row.getValue("SHAPE@AREA")

Hardcoding Paths is Bad Practice

Avoid putting full paths directly in your tools. Use variables or, even better, allow the user to provide them via command-line arguments.

  • Bad (Hardcoded):

    arcpy.management.Buffer("C:\\Data\\Parcels.shp", "C\\Data\\Parcels_Buffer.shp", "100 meters")
  • Good (Using variables):

    import arcpy
    input_fc = r"C:\Data\Parcels.shp"
    output_fc = r"C:\Data\Parcels_Buffer.shp"
    arcpy.management.Buffer(input_fc, output_fc, "100 meters")

Error Handling: Use try...except

ArcGIS operations can fail for many reasons (e.g., a locked file, a broken network path, invalid data). Always wrap your geoprocessing logic in a try...except block to handle errors gracefully.

  • Good:

    import arcpy
    try:
        print("Starting buffer operation...")
        arcpy.management.Buffer("Parcels", "Parcels_Buffer", "500 feet")
        print("Buffer completed successfully!")
    except arcpy.ExecuteError:
        # Handle ArcGIS specific errors
        print("ArcGIS Tool Error:")
        print(arcpy.GetMessages(2)) # Print error messages
    except Exception as e:
        # Handle any other unexpected errors
        print(f("An unexpected error occurred: {e}"))

Documentation and Comments

Docstrings for Functions and Scripts

Use triple-quoted strings ("""Docstring""") to document what your functions or entire scripts do. A good docstring includes:

  • A one-line summary.

  • A more detailed description.

  • Information about arguments (Args:).

  • Information about what is returned (Returns:).

  • Good:

    import arcpy
    def buffer_features(input_fc, output_fc, distance):
        """
        Buffers a feature class by a specified distance.
        Args:
            input_fc (str): Path to the input feature class.
            output_fc (str): Path to the output feature class.
            distance (str): The buffer distance (e.g., "100 meters").
        Returns:
            str: Path to the created output feature class.
        """
        arcpy.management.Buffer(input_fc, output_fc, distance)
        return output_fc
    # For a standalone script, a "header" docstring is useful
    """
    -----------------------------------------------------------------------------
    Script: BufferParcels.py
    Author: Your Name
    Date: 2025-10-27
    Description: This script buffers all parcel features in a geodatabase by 500
                 feet and saves the result to a new feature class.
    Usage: BufferParcels.py
    -----------------------------------------------------------------------------
    """

Inline Comments for Complex Logic

Don't comment on obvious things. Comment on the why, not the what.

  • Bad (Commenting the obvious):
    # This is a for loop
    for row in cursor:
        # This gets the OID
        oid = row[0]
  • Good (Commenting the intent):
    # Filter for parcels larger than 1 acre to reduce processing time
    with arcpy.da.SearchCursor("Parcels", ["OID@", "SHAPE@AREA"]) as cursor:
        for row in cursor:
            # Area is in square meters; 1 acre = 4046.86 sq meters
            if row[1] > 4046.86:
                # ... process large parcel
                pass

Putting It All Together: A Complete Example

Here is a script that incorporates many of these principles.

# -----------------------------------------------------------------------------
# Script: CreateAndBufferParcels.py
# Author: Your Name
# Date: 2025-10-27
# Description: Creates a new point feature class from an address table, 
#              geocodes the addresses, and buffers the points.
# Usage: CreateAndBufferParcels.py
# -----------------------------------------------------------------------------
import arcpy
import os
# --- Configuration ---
# Use constants for values that might change
WORKSPACE = r"C:\Data\Project.gdb"
ADDRESS_TABLE = "Addresses.csv"
OUTPUT_POINTS = "GeocodedAddresses"
BUFFER_DISTANCE = "500 feet"
OUTPUT_BUFFER = "AddressPoints_Buffer"
def main():
    """
    Main execution function for the script.
    """
    try:
        # Set environment settings
        arcpy.env.workspace = WORKSPACE
        arcpy.env.overwriteOutput = True # Useful for development
        print("Starting geocoding process...")
        # Step 1: Create a point feature class from an address table
        # Use descriptive variable names
        address_fields = ["Address", "City"]
        xy_fields = ["Address", "City"]
        arcpy.management.XYTableToPoint(
            ADDRESS_TABLE, 
            OUTPUT_POINTS, 
            "Address", # X field
            "City",    # Y field (optional if addresses are complete)
            coordinate_system=arcpy.SpatialReference(26910) # NAD_1983_UTM_Zone_10N
        )
        print(f"Successfully created point feature class: {OUTPUT_POINTS}")
        # Step 2: Buffer the new points
        print(f"Buffering points by {BUFFER_DISTANCE}...")
        arcpy.management.Buffer(
            in_features=OUTPUT_POINTS,
            out_feature_class=OUTPUT_BUFFER,
            buffer_distance_or_field=BUFFER_DISTANCE
        )
        print(f"Buffering complete. Output saved to: {OUTPUT_BUFFER}")
        print("\nScript finished successfully!")
    except arcpy.ExecuteError:
        # Handle errors from ArcGIS tools
        print("\n--- ARCGIS TOOL ERROR ---")
        print(arcpy.GetMessages(2))
    except Exception as e:
        # Handle any other unexpected errors
        print(f"\n--- UNEXPECTED ERROR ---")
        print(f"An error occurred: {e}")
if __name__ == "__main__":
    # This ensures the main() function is called only when the script
    # is executed directly, not when imported as a module.
    main()
分享:
扫描分享到社交APP
上一篇
下一篇