Add multiple shapefiles to MXD with arcpy - python

I am trying to add multiple files to an MXD file using some of the code found here:
How do I add a shapefile in ArcGIS via python scripting?
The code below does not return any errors, however none of the shapefiles seem to get added to the blank mxd document.
Any help as to why this is not working would be appreciated.
import arcpy
import arcpy.mapping
from shutil import copyfile
from os import listdir
from os.path import isfile, join
def AddAllShapeFilesToNewMXD(source_directory):
# Source file is the template that the will be copied to the directory with
# All the shape files in it.
source_file = 'M:\Ops Field Map\Blank Map.mxd'
# Output file is the name of the file that will have the shape files added to it
output_file = 'GPS_Map'
rev_count = 0
while isfile(join(source_directory, output_file + '.mxd')):
#Make sure a unique file is created
print ('File ' + output_file + '.mxd exists.'),
rev_count += 1
output_file = output_file + '_rev' + str(rev_count)
print ('Trying ' + output_file + '.mxd ...')
# Create the destination file. This is the file the shape files are added to
destination_file = join(source_directory, output_file + '.mxd')
copyfile(source_file, destination_file)
print 'MXD file created: ' + destination_file
# Get the map doccument
mxd = arcpy.mapping.MapDocument(destination_file)
# Get the data frame
data_frame = arcpy.mapping.ListDataFrames(mxd, "*")[0]
# Get a list of all the shape files
shp_files = [ f for f in listdir(source_directory) if isfile(join(source_directory, f)) and f.endswith('.shp') ]
# Add all the shapefiles to the mxd file
for s in shp_files:
new_layer_full_path = join(source_directory, s)
new_layer = arcpy.mapping.Layer(new_layer_full_path)
arcpy.mapping.AddLayer(data_frame, new_layer, "BOTTOM")
print 'Layer added ' + new_layer_full_path
del new_layer
return True
directory = 'C:\Users\gps\Desktop\dd test'
AddAllShapeFilesToNewMXD(directory)

It is hard to know without files to play with, but one reason the code above may not be giving an error but not displaying anything is that for many arcgis map display operations, you have to make sure that the arcgis geoprocessing option of 'add results of geoprocessing operations to the display' under geoprocessing> geoprocessing options is turned on.

It could be that you are missing those two important lines:
arcpy.RefreshActiveView()
arcpy.RefreshTOC()

Looks like you're almost there and that both Lucas and BelowZero are offering good suggestions if your code is running w/in a active session. If it's creating an *.mxd for later use, I don't see where the results are saved. Here's some simpler sample code, note the last line:
mxd = arcpy.mapping.MapDocument(srcdir+'/data_bin/Untitled.mxd')
data_frame = arcpy.mapping.ListDataFrames(mxd)[0]
mxd.activeView = data_frame.name
flowlinesLyr=arcpy.mapping.Layer('..\\NHDPlus\\nhdflowline_en')
flowlinesLyr.name='NHDPlus Flowlines'
arcpy.mapping.AddLayer (data_frame, flowlinesLyr,'TOP')
gagesEventLyr=arcpy.mapping.Layer('..\\NHDPlus\\StreamGageEvent')
gagesEventLyr.name='Original stream gage locations'
arcpy.mapping.AddLayer (data_frame, gagesEventLyr,'TOP')
mxd.saveACopy(datadir+'\NHDPlus'+Region+'_Gage_QAQC.mxd')

Related

How to select only a file type with os.listdir?

after having concatenated 10 strips of the same image, I want to convert them into reflectance and therefore divide them by 10,000. Nevertheless I have two types of files in my folders, except I want to apply my code only to my.img file and not to the.hdr...
Do you know how I can proceed to make this selection with os.listdir?
my code is as follows :
import os
import spectral as sp
import spectral.io.envi as envi
src_directory = "/d/afavro/Bureau/3_stack/"
dossier = os.listdir (src_directory)
print(dossier)
for fichier in dossier:
print (fichier)
ssrc_directory = "/d/afavro/Bureau/3_stack/" + fichier
rasters = os.listdir (ssrc_directory)
print(rasters)
OUTPUT_FOLDER = "/d/afavro/Bureau/4_reflectance/" + 'reflectance_' + fichier
print(OUTPUT_FOLDER)
if not os.path.exists(OUTPUT_FOLDER):
os.makedirs(OUTPUT_FOLDER)
for image in rasters:
print (image)
img = sp.open_image(image)
print("%s opened successfully" %os.path.basename(image))
im_HS = img[:,:,:]/10000
header = envi.read_envi_header('/d/afavro/Bureau/3_stack/'+ image)
#Save index image
sp.envi.save_image(OUTPUT_FOLDER + '/reflectance_' + image, im_HS, metadate = header, force = True, interleave = 'bsq')
I think that making a yew loop would be a good idea but I don't know how to do it...
Ideas ?
Find the extension of the file using os.path.splitext
for f in os.listdir('<path>'):
name, ext = os.path.splitext(f)
if ext == '.img':
#do stuff
Why don't you use glob?
from glob import glob
for f in glob('/your/path/*.img'):
pass # add your code here
Hello You can use use Pathlib as an object oriented Path management library
and do something like
from Pathlib2 import Path
pattern_1 = "type1"
pattern_2 = "type2"
list_pattern_1_files = list(Path(<YOUR_PATH>).glob(f'**/*.{pattern_1}'))
list_pattern_2_files = list(Path(<YOUR_PATH>).glob(f'**/*.{pattern_2}'))

Reading multiple excel files and writting it to multiple excel files in python

I have written code where it is reading excel file and then after processing required function I want to write it to Excel file . Now I have done this for one excel file . and now my question is when I want to do it for multiple excel file that is reading multiple excel file and then output should be also in multiple excel file how will I apply for loop here so I get separate output excel file for each input file
Following is my code
from ParallelP import *
import time,json
import pandas as pd
if __name__ == '__main__':
__ip__ = "ip/"
__op__ = "op/"
__excel_file_name__ = __ip__ + '80chars.xlsx'
__prediction_op__ = __op__ + basename(__excel_file_name__) + "_processed.xlsx"
df = pd.read_excel(__excel_file_name__)
start_time = time.time()
df_preprocessed = run(df)
print("Time Needed to execute all data is {0} seconds".format((time.time() - start_time)))
print("Done...")
df_preprocessed.to_excel(__prediction_op__)
I tried to stick to your example and just expand it as I would do it. The below example is untested and does not mean that it is the best way to do it!
from ParallelP import *
import time,json
import pandas as pd
import os
from pathlib import Path # Handles directory paths -> less error prone than manually sticking together paths
if __name__ == '__main__':
__ip__ = "ip/"
__op__ = "op/"
# Get a list of all excel files in a given directory
excel_file_list = [f for f in os.listdir(__ip__) if f.endswith('.xlsx')]
# Loop over the list and process each excel file seperately
for excel_file in excel_file_list:
excel_file_path = Path(__ip__, excel_file) # Create the file path
df = pd.read_excel(str(excel_file)) # Read the excel file to data frame
start_time = time.time()
df_preprocessed = run(df) # Run your routine
print("Time Needed to execute all data is {0} seconds".format((time.time() - start_time)))
print("Done...")
# Create the output file name
prediction_output_file_name = '{}__processed.xlsx'.format(str(excel_file_path.resolve().stem))
# Create the output file path
prediction_output_file_path = str(Path(__op__, prediction_output_file_name))
# Write the output to the excel file
df_preprocessed.to_excel(prediction_output_file_path)
Sidenote: I have to mention that your variable names feel like a misuse of the __ . These 'dunder' functions are special and indicate that they have a meaning for python (see for example here). Please, just name your variables input_dir and output_dir instead of __ip__ and __op__, respectively.
I do have some code i wrote. Maybe you can alter this for your requirements.
# This is where your input file should be
in_folder = 'input/xls/file/folder'
# This will be your output folder
out_folder = 'output/xls/file/folder'
if not os.path.exists(out_folder):
os.makedirs(out_folder)
file_exist = False
dir_list = os.listdir(in_folder)
for xlfile in dir_list:
if xlfile.endswith('.xlsx') or xlfile.endswith('.xls'):
file_exist = True
str_file = os.path.join(in_folder, xlfile)
#work_book = load_workbook(filename=str_file)
#work_sheet = work_book['qa']
#Do ur work hear with excel
#out_Path = os.path.join(out_folder,)
#and output it to the out_Path
if not file_exist:
print('cannot find any valid excel file in the folder ' + in_folder)

Creating Multiple featureclasses from data in .txt Files

I am trying to create multiple feature classes from data with .txt extension. My code runs, but only produces one .shp file. The variable xyTable when checked does contain all the file extensions. These then should individually run through both Arcpy functions and produce the relevant featureclass files named in accordance with their .txt files.
import arcpy
import os
import tempfile
import shutil
shpFileArray = []
print "\n"
arcpy.env.overwriteOutput = True
newFolder = "destinationpath"
if os.path.exists(newFolder):
tmp = tempfile.mktemp(dir=os.path.dirname(newFolder))
shutil.move(newFolder, tmp)
shutil.rmtree(tmp)
os.makedirs(newFolder)
arcpy.env.workspace = newFolder
for file in os.listdir("sourcepath"):
layerName = file[:-4]
fileSHP = layerName+".shp"
for file in os.listdir("sourcepath"):
if file.endswith(".txt"):
xyTable = (os.path.join("destinationpath", file))
arcpy.MakeXYEventLayer_management(table= xyTable, in_x_field="EastingM", in_y_field="NorthingM", out_layer="layerName",...continues...
arcpy.FeatureClassToFeatureClass_conversion(in_features="layerName", out_path="destinationpath", out_name= fileSHP,....continues....
Looks like you are not giving the FeatureClassToFeatureClass tool unique shapefile names. After the first For loop finishes, fileSHP doesn't change. Looks like you have the shpFileArray set up to hold the list of fileSHPs. Perhaps try something like this to save your set of fileSHPs in the first For loop and refer to them in the second For loop. My python might not be exactly right, but I think the idea is.
import arcpy
import os
import tempfile
import shutil
shpFileArray = []
print "\n"
arcpy.env.overwriteOutput = True
newFolder = "destinationpath"
if os.path.exists(newFolder):
tmp = tempfile.mktemp(dir=os.path.dirname(newFolder))
shutil.move(newFolder, tmp)
shutil.rmtree(tmp)
os.makedirs(newFolder)
arcpy.env.workspace = newFolder
for file in os.listdir("sourcepath"):
layerName = file[:-4]
fileSHP = layerName+".shp"
shpFileArray.append(fileSHP)
for idx, file in enumerate(os.listdir("sourcepath")):
if file.endswith(".txt"):
xyTable = (os.path.join("destinationpath", file))
outShape = shapeFileArray[idx]
arcpy.MakeXYEventLayer_management(table= xyTable, in_x_field="EastingM", in_y_field="NorthingM", out_layer="layerName",...continues...
arcpy.FeatureClassToFeatureClass_conversion(in_features="layerName", out_path="destinationpath", out_name= outShape,....continues....

Exporting multiple files with different filenames

Lets say I have n files in a directory with filenames: file_1.txt, file_2.txt, file_3.txt .....file_n.txt. I would like to import them into Python individually and then do some computation on them, and then store the results into n corresponding output files: file_1_o.txt, file_2_o.txt, ....file_n_o.txt.
I've figured out how to import multiple files:
import glob
import numpy as np
path = r'home\...\CurrentDirectory'
allFiles = glob.glob(path + '/*.txt')
for file in allFiles:
# do something to file
...
...
np.savetxt(file, ) ???
Not quite sure how to append the _o.txt (or any string for that matter) after the filename so that the output file is file_1_o.txt
Can you use the following snippet to build the output filename?
parts = in_filename.split(".")
out_filename = parts[0] + "_o." + parts[1]
where I assumed in_filename is of the form "file_1.txt".
Of course would probably be better to put "_o." (the suffix before the extension) in a variable so that you can change at will just in one place and have the possibility to change that suffix more easily.
In your case it means
import glob
import numpy as np
path = r'home\...\CurrentDirectory'
allFiles = glob.glob(path + '/*.txt')
for file in allFiles:
# do something to file
...
parts = file.split(".")
out_filename = parts[0] + "_o." + parts[1]
np.savetxt(out_filename, ) ???
but you need to be careful, since maybe before you pass out_filename to np.savetxt you need to build the full path so you might need to have something like
np.savetxt(os.path.join(path, out_filename), )
or something along those lines.
If you would like to combine the change in basically one line and define your "suffix in a variable" as I mentioned before you could have something like
hh = "_o." # variable suffix
..........
# inside your loop now
for file in allFiles:
out_filename = hh.join(file.split("."))
which uses another way of doing the same thing by using join on the splitted list, as mentioned by #NathanAck in his answer.
import os
#put the path to the files here
filePath = "C:/stack/codes/"
theFiles = os.listdir(filePath)
for file in theFiles:
#add path name before the file
file = filePath + str(file)
fileToRead = open(file, 'r')
fileData = fileToRead.read()
#DO WORK ON SPECIFIC FILE HERE
#access the file through the fileData variable
fileData = fileData + "\nAdd text or do some other operations"
#change the file name to add _o
fileVar = file.split(".")
newFileName = "_o.".join(fileVar)
#write the file with _o added from the modified data in fileVar
fileToWrite = open(newFileName, 'w')
fileToWrite.write(fileData)
#close open files
fileToWrite.close()
fileToRead.close()

Script that reads PDF metadata and writes to CSV

I wrote a script to read PDF metadata to ease a task at work. The current working version is not very usable in the long run:
from pyPdf import PdfFileReader
BASEDIR = ''
PDFFiles = []
def extractor():
output = open('windoutput.txt', 'r+')
for file in PDFFiles:
try:
pdf_toread = PdfFileReader(open(BASEDIR + file, 'r'))
pdf_info = pdf_toread.getDocumentInfo()
#print str(pdf_info) #print full metadata if you want
x = file + "~" + pdf_info['/Title'] + " ~ " + pdf_info['/Subject']
print x
output.write(x + '\n')
except:
x = file + '~' + ' ERROR: Data missing or corrupt'
print x
output.write(x + '\n')
pass
output.close()
if __name__ == "__main__":
extractor()
Currently, as you can see, I have to manually input the working directory and manually populate the list of PDF files. It also just prints out the data in the terminal in a format that I can copy/paste/separate into a spreadsheet.
I'd like the script to work automatically in whichever directory I throw it in and populate a CSV file for easier use. So far:
from pyPdf import PdfFileReader
import csv
import os
def extractor():
basedir = os.getcwd()
extension = '.pdf'
pdffiles = [filter(lambda x: x.endswith('.pdf'), os.listdir(basedir))]
with open('pdfmetadata.csv', 'wb') as csvfile:
for f in pdffiles:
try:
pdf_to_read = PdfFileReader(open(f, 'r'))
pdf_info = pdf_to_read.getDocumentInfo()
title = pdf_info['/Title']
subject = pdf_info['/Subject']
csvfile.writerow([file, title, subject])
print 'Metadata for %s written successfully.' % (f)
except:
print 'ERROR reading file %s.' % (f)
#output.writerow(x + '\n')
pass
if __name__ == "__main__":
extractor()
In its current state it seems to just prints a single error (as in, the error message in the exception, not an error returned by Python) message and then stop. I've been staring at it for a while and I'm not really sure where to go from here. Can anyone point me in the right direction?
writerow([file, title, subject]) should be writerow([f, title, subject])
You can use sys.exc_info() to print the details of your error
http://docs.python.org/2/library/sys.html#sys.exc_info
Did you check the pdffiles variable contains what you think it does? I was getting a list inside a list... so maybe try:
for files in pdffiles:
for f in files:
#do stuff with f
I personally like glob. Notice I add * before the .pdf in the extension variable:
import os
import glob
basedir = os.getcwd()
extension = '*.pdf'
pdffiles = glob.glob(os.path.join(basedir,extension)))
Figured it out. The script I used to download the files was saving the files with '\r\n' trailing after the file name, which I didn't notice until I actually ls'd the directory to see what was up. Thanks for everyone's help.

Categories