Select to view content in your preferred language

For each .LYRX in a folder, if >0 rows returned, send email

1056
5
03-13-2023 12:48 AM
Bud
by
Esteemed Contributor

What would it take to do the following in a Python script? (script to be run weekly on a server as a Windows scheduled task)

  1. For each .LYRX layer file in a network folder
    • The layer file is based on an Oracle EGDB query layer that has a WHERE clause.
  2. If the query layer returns any rows in the attribute table
  3. Then send an email to me with the details.
    For example:
    • Subject: Issues found in OutOfDateConstructionProjects.LYRX
    • Body: Records were found in the OutOfDateConstructionProjects.LYRX query. Please investigate.

The assumption being my IT department will be able to set up SMTP.
ArcGIS Pro 3.1. ArcGIS Notebook Server is not an option.

I’m inexperienced with Python. So any help would be appreciated.

0 Kudos
5 Replies
Kara_Shindle
Frequent Contributor

If you want to write a script for this, start out with pseudo code.  Write what you want it to do, logically, step-by-step.  It will help when you go to fill in the code bits and will most likely be the beginning of your comments.

One way I'd attempt this is probably by using a search cursor to iterate through every file in the folder, checking the # of rows in your attribute table.

I would actually suggest storing the results of your search, and then sending all of the results in one email.  That way, you don't potentially end up with 100 emails if you have 100 LYRX files that fit this criteria.

So that would probably mean you create a list/dictionary that stores the name of each file that you test that returns as TRUE for your query.  Then you can create an email, dump the list into an email, and send it off.  IF your dictionary is empty, then no email.

 

 

Roughly, I think your script could follow the below steps.

 

 

#import modules

#set variables

#search through folder & store files that meet criteria
For every file in folder:
    count number of rows
        if row > 0:
            add name to list
#Create an email and dump list/dictionary of file names into the message body
Is list empty?
    No email
Does list have entries?
    create email
    identify receivers
    drop list into body
    

 

 

 

TorbjørnDalløkken2
Frequent Contributor

Hi.

To do the task that you describe, you need to create a pythonscript that finds all the lyrx files in the directory, then create a featurelayer and get the number of features of that layer. There are several options for getting the layerfiles, using the modules os, glob or pathlib (from Python 3.4). This example uses the glob-module 

 

import glob

folder = r'C:\Maps\LayerFiles\*.lyrx' # your folder with lyrx
elements = glob.glob(folder) #get the files

 

Then you need to iterate each of the files, create a featurelayer and get the number of features:

 

for element in elements:
  featurelayer = "FeatureLayer"
  arcpy.MakeFeatureLayer_management(in_features=element, out_layer=featurelayer) # create featurelayer from element
    c = arcpy.GetCount_management(featurelayer) # get count of features
    arcpy.Delete_management(in_data=featurelayer) # delete featurelayer

 

For sending the e-mail, you need to use the smtp-library, and call the sendEmail method each time the count is greater than 0. You can see the use of the smtplib here:

 

import smtplib

def sendEmail(layername):
  sender = 'from@fromdomain.com'
  receivers = ['to@todomain.com']

  message = """From: From Person <from@fromdomain.com>
  To: To Person <to@todomain.com>
  Subject:  Issues found in {0} 

  Records where found in the {0} query. Please investigate""".format(layername)

  try:
    smtpObj = smtplib.SMTP('localhost')
    smtpObj.sendmail(sender, receivers, message)         
    print "Successfully sent email"
  except SMTPException:
    print "Error: unable to send email"

 

 

Good luck 🙂

Bud
by
Esteemed Contributor

For my notes, the requirements in the original post are over-simplified -- just to keep things simple for a first attempt at the script. Ultimately, I think I'd need a table (CSV?) in the network folder that would store information like:

  1. DISTRIBUTION_LIST: jdoe@domain.com, jsmith@domain.com, jbrown@domain.com
  2. And possibly other columns:
    • DESCRIPTION
    • MESSAGE
    • EMAIL_SCHEDULE
    • COMMENTS
    • .LYRX layer file path/name

So eventually, the Python script would need to loop through the table and read the values.

0 Kudos
Kara_Shindle
Frequent Contributor

I do something like that.  Below is a simple code I use to read a list of features (unique identifier is used) from a CSV and then do something with them (in this case, it just creates a selection).

 

 

import csv
import os
import arcpy

workspace = '[FILE PATH]'
selList = "selection.csv"

#opens up my csv
csvRead = open(os.path.join(workspace, selList), 'r') 
with csvRead as r:
# creates a list
	csvList = []
	reader = csv.reader(r, delimiter = ',')'
#reads the rows in the CSV from column A
#for every row in Col A, it adds the value to a list selecting only certain characters
	for row in reader:
		UPI = row[0]
		clippedUPI = UPI[0:23]
		csvList.append(clippedUPI)
#this part does something with my list of values, in this case adding it to #an existing selection
for x in csvList:
	selection = '"Name" = ' + "'" + x + "'"
	arcpy.SelectLayerByAttribute_management(r"Parcel Fabric\Parcels", "ADD_TO_SELECTION", selection)
print("Selection Completed")
del selList, csvRead

 

 

by Anonymous User
Not applicable

I keep a list of mine in an .ini file (fancy txt file really) as fc | email distro list since we have different people to email based on the dataset.

anx_no | email one, email two, email three, email four
anx_on | email one, email two, email three
 

 

import arcpy
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

iniFile = 'editNotifications.ini'
fclist = [line.rstrip('\n') for line in open(iniFile)]

for l in fclist:
    fc_con = fr'path to lyrx maybe\{l.split(" | ")[0]}'

    if int(arcpy.GetCount_management(fc_con).getOutput(0)) > 0:

        # Create the body of the message (a plain-text and an HTML version).
        disclaim = "so they know its auto generated.\n"
        # formatting lines
        text = "\n\n" + f'{fc_con.split(".")[-1]} has {arcpy.GetCount_management(fc_con).getOutput(0)}'

        # Create the root message and fill in the from, to, and subject headers
        msg = MIMEMultipart('related')

        msg['From'] = 'spoofer@mydomain.gov'
        msg['To'] = ','.join([x.rstrip() for x in l.split(' | ')[1].split(', ')])
        msg['Subject'] = f'{l.split(" | ")[0]} has edits'

        msgText = MIMEText(str(disclaim + text), 'plain')

        # Send the email
        smtp = smtplib.SMTP('smtp.domain.gov')

        smtp.send_message(msg, msg['From'], msg['To'])
        smtp.quit()

    else:
        print('yuppers')