You could use the gdal.Translate function and pass a list of bands to keep (bandList argument):
from osgeo import gdal source_dataset = "input1.tif" output_dataset = "output1.tif" bad_bands = ( (1, 2, 3), range(130, 142), # note 142 as range func excludes the last value, so this will give you 130-141 range(191, 214), range(272, 285) ) src = gdal.OpenEx(source_dataset) bad_bands = [b for bands in bad_bands for b in bands] # flatten nested tuples and ranges into a single list all_bands = range(1, src.RasterCount+1) # Note GDAL band numbers start at 1 keep_bands = [b for b in all_bands if not b in bad_bands] out = gdal.Translate(output_dataset, src, bandList=keep_bands)
Or with rasterio, you could write each band out separately (to the same raster):
import rasterio as rio source_dataset = "input1.tif" output_dataset = "output1.tif" bad_bands = ( (1, 2, 3), range(130, 142), # note 142 as range func excludes the last value range(191, 214), range(272, 285) ) with rio.open(source_dataset) as src: profile = src.profile.copy() bad_bands = [b for bands in bad_bands for b in bands] # flatten nested tuples and ranges into a single list all_bands = range(1, src.count+1) # Note Rasterio band numbers start at 1 keep_bands = [b for b in all_bands if not b in bad_bands] profile.update(count=len(keep_bands)) with rio.open(output_dataset, "w", **profile) as out: for i, b in enumerate(keep_bands, start=1): out.write(src.read(b), i)