Search code examples
pythonarcgisarcpy

Using variables and loops to open multiple files for arcpy


I am trying to use a variable and a loop to open multiple files within a function. What I have is:

import os
import arcpy.geoprocessing

path = r"F:\Earth\2018\Bands\\"
files = os.listdir(path)

RowColumn = []
for TIF in files:
    firstsix = TIF[0:6]
    RowColumn.append(firstsix)
RowColumn = list(dict.fromkeys(RowColumn))

year= ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020']

for code in RowColumn:
    with arcpy.EnvManager(scratchWorkspace=r"F:\Earth\'year'\project_'year'\project_'year'.gdb",
    workspace=r"F:\Earth\'year'\project_'year'\project_'year'.gdb"):
        arcpy.management.CompositeBands(
            r"F:\Earth\'year'\Bands\'code'_'year'_B2.TIF;"
            r"F:\Earth\'year'\Bands\'code'_'year'_B3.TIF;"
            r"F:\Earth\'year'\Bands\'code'_'year'_B4.TIF;"
            r"F:\Earth\'year'\Bands\'code'_'year'_B5.TIF;"
            r"F:\Earth\'year'\Bands\'code'_'year'_B6.TIF;"
            r"F:\Earth\'year'\Bands\'code'_'year'_B7.TIF",
            r"F:\Earth\'year'\project_'year'\project_'year'.gdb\a'code'_'year'")

I have renamed each file to be something like "042024_2017_B2.TIF" so that the first 6 numbers are the code for the TIF file location, then the year in the middle, then the band number. I have about 80 images per year and each image has 6 bands. The RowNames print perfectly when printed (all 6 digit codes as the first 6 digits of the file names).

I need the items in RowNames to be inserted where ever it says 'code' and I need the year to be inserted wherever I put 'year'. How do I do this?

This code gives me the errors: ERROR 000732: Input Rasters: Dataset F:\Earth'year'\Bands'code'_'year'_B2.TIF does not exist or is not supported ERROR 000354: The name contains invalid characters Failed to execute (CompositeBands).

So it isn't recognizing the variable names I tried to assign but I don't know how to fix that.

EDIT:

Here is the code that ended up working with a big thanks to @AlexK :

import os
import arcpy.geoprocessing

years = ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020']
print(years)
#Renaming the files
for year in years:
    path = fr"F:\Earth\{year}\Bands\\"
    files = os.listdir(path)
    # rename the files
    for file in files:
        src = path + file
        code = file[10:21]
        band = file[40:]
        dst = path + code + band
        os.renames(src, dst)

for year in years:
#Setting the path again, likely redundant
    path = fr"F:\Earth\{year}\Bands\\"
    files = os.listdir(path)
#Make a list of the unique codes
    RowColumn = []
    for TIF in files:
        firstsix = TIF[0:6]
        RowColumn.append(firstsix)
    RowColumn = list(dict.fromkeys(RowColumn))
    print(RowColumn)
    # Make a loop to run the functions for each code
    for code in RowColumn:
        # Make the Composite Bands (one photo with all the layers)
        with arcpy.EnvManager(scratchWorkspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb",
                              workspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb"):
            arcpy.management.CompositeBands(
                fr"F:\Earth\{year}\Bands\{code}_{year}_B2.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B3.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B4.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B5.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B6.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B7.TIF",
                fr"F:\Earth\{year}\project_{year}\project_{year}.gdb\a{code}_{year}")
        # This copies and deletes the null values, so I can mosaic them together.
        with arcpy.EnvManager(scratchWorkspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb",
                              workspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb"):
            arcpy.management.CopyRaster(fr"a{code}_{year}",
                                        fr"F:\Earth\{year}\project_{year}\project_{year}.gdb\c{code}_{year}", '', 0,
                                        "0", "NONE", "NONE", "16_BIT_UNSIGNED", "NONE", "NONE", "TIFF", "NONE",
                                        "CURRENT_SLICE", "NO_TRANSPOSE")
        # Once it is here, I want it to delete the bands from the bands folder and the composite bands
        for fname in files:
            if fname.startswith(code):
                os.remove(os.path.join(path, fname))
        print({code})

Solution

  • The r literal prefix can only be applied to string literals, so you won't be able to insert variable names there. If you have Python 3.6+, you can convert all those strings to raw f-strings.

    (First, you should change your year variable to a string: year = '2018'.)

    Then, try:

    for code in RowColumn:
        with arcpy.EnvManager(scratchWorkspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb",
        workspace=fr"F:\Earth\{year}\project_{year}\project_{year}.gdb"):
            arcpy.management.CompositeBands(
                fr"F:\Earth\{year}\Bands\{code}_{year}_B2.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B3.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B4.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B5.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B6.TIF;"
                fr"F:\Earth\{year}\Bands\{code}_{year}_B7.TIF",
                fr"F:\Earth\{year}\project_{year}\project_{year}.gdb\a{code}_{year}")