<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Writing better Python Code in Python Questions</title>
    <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530727#M41522</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Good suggestions by &lt;A href="https://community.esri.com/migrated-users/48550"&gt;Blake T&lt;/A&gt;‌.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Some more&amp;nbsp; (though not specifically for your script) can be found here: &lt;A href="https://community.esri.com/docs/DOC-1927"&gt;Some Python Snippets&lt;/A&gt; &lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Wed, 11 Feb 2015 21:11:08 GMT</pubDate>
    <dc:creator>XanderBakker</dc:creator>
    <dc:date>2015-02-11T21:11:08Z</dc:date>
    <item>
      <title>Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530724#M41519</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hey everyone,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Wanted to ask a generic but help question of the community.&amp;nbsp; Currently I have been learning Python on my own and have just completed what I call my first "real world use" script for my company.&amp;nbsp; It is a pretty basic script but am trying to get better.&amp;nbsp; This script could be used by multiple people who don't know anything about python.&amp;nbsp; I wanted to see for them, and myself if there are improvements that I could make to make this script more robust and "user friendly".&amp;nbsp; I am using all this as a learning process.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Any help, ideas, opinions, comments would be fantastic.&lt;/P&gt;&lt;P&gt;-Matt&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;
import time, sys, platform, imp, arcpy
start = (time.strftime('%x %X')) # Start time

##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS #####

arcpy.env.workspace = 'insert path' # Location of output files
newInput = 'insert path' # Input File (New Year)
clipFeat = 'insert path' # Clip Feature
eraseFeat = 'insert path' # Previous years merge
x = '2014' # Change for current year
year = str(x) # Input file year (Change only the year)
outClip = 'r' + x + 'C' # Clip Output
outLayer = 'Query_Layer' # Layer output (Used to run the query)
outFc = 'Query_' + outClip # Shapefile output from the Layer file
eraseOut = 'r' + x + 'E' # Erase output

arcpy.env.overwriteOutput = 1 # Allows for output file overwriting
messageList = [] # Message list for the log file

log = 'insert path' # Creates a .txt doc with a log of the geoprocessing tools run (Edit path)

##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS ##### MUST EDIT THESE INPUTS #####

# Clip file to specified parameter
arcpy.Clip_analysis(newInput, clipFeat, outClip)
messageList.append(arcpy.GetMessages())

# Create a layer to add to Table of Contents
newLyr = arcpy.MakeFeatureLayer_management(outClip, outLayer)[0]
messageList.append(arcpy.GetMessages())

# Add year field and Calculate Field
arcpy.AddField_management(outClip, "Year", "TEXT", 0, "", 10, "","NULLABLE", "NON_REQUIRED","")
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, 'Year', year, "PYTHON_9.3", "")
messageList.append(arcpy.GetMessages())

# Add Fields and run USDA QUERY on the Layer
arcpy.AddField_management(outLayer, "BType", "TEXT", 0, "", 10, "","NULLABLE", "NON_REQUIRED","")
messageList.append(arcpy.GetMessages())
arcpy.AddField_management(outLayer, "MPB_Only", "TEXT", 0, "", 10, "","NULLABLE", "NON_REQUIRED","")
messageList.append(arcpy.GetMessages())
arcpy.AddField_management(outLayer, "Aspen_Dec", "TEXT", 0, "", 10, "","NULLABLE", "NON_REQUIRED","")
messageList.append(arcpy.GetMessages())&amp;nbsp;&amp;nbsp; 

# Query the data, based on the provided information from the USDA (Forest Service)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
# MPB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' "DCA1" = 80003 OR "DCA2" = 80003 OR "DCA3" = 80003 OR "DCA1" = 11006 OR "DCA2" = 11006 OR "DCA3" = 11006 ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "MPB_Only", 'str("MPB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# LP
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 11006 AND "HOST1" = 108) OR ("DCA2" = 11006 AND "HOST2" = 108) OR ("DCA3" = 11006 AND "HOST3" = 108) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("LP")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# PP
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 11006 AND "HOST1" = 122) OR ("DCA2" = 11006 AND "HOST2" = 122) OR ("DCA3" = 11006 AND "HOST3" = 122) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("PP")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# 5N
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 80003) OR ("DCA2" = 80003) OR ("DCA3" = 80003) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("SN")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# SB
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 11009) OR ("DCA2" = 11009) OR ("DCA3" = 11009) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("SB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# DFB
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 11007) OR ("DCA2" = 11007) OR ("DCA3" = 11007) ')&amp;nbsp;&amp;nbsp;&amp;nbsp; 
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("DFB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# WBBB
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 80002) OR ("DCA2" = 80002) OR ("DCA3" = 80002) ')&amp;nbsp;&amp;nbsp;&amp;nbsp; 
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("WBBB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# WSB
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 12040) OR ("DCA2" = 12040) OR ("DCA3" = 12040) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("WSB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# WPB
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 11002) OR ("DCA2" = 11002) OR ("DCA3" = 11002) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "BType", 'str("WPB")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")
# Aspen Decline
arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' ("DCA1" = 80001) OR ("DCA2" = 80001) OR ("DCA3" = 80001) OR ("DCA1" = 24032) OR ("DCA2" = 24032) OR ("DCA3" = 24032) ')
messageList.append(arcpy.GetMessages())
arcpy.CalculateField_management(outLayer, "Aspen_Dec", 'str("AD")', "PYTHON_9.3", "")
arcpy.SelectLayerByAttribute_management(outLayer, "CLEAR_SELECTION")

# Creates a Shape file from the layer
arcpy.CopyFeatures_management(outLayer, outFc)
messageList.append(arcpy.GetMessages())

# Erase
arcpy.Erase_analysis(outFc, eraseFeat, eraseOut)
messageList.append(arcpy.GetMessages())

# Writes information to log file
f = open(log, 'w') # Log file location
f.write('Created by: Matt Russo' + '\n') 
&lt;SPAN&gt;f.write('Email: &lt;/SPAN&gt;&lt;A class="jive-link-email-small" href="mailto:matthewrusso1986@gmail.com" rel="nofollow noopener noreferrer" target="_blank"&gt;matthewrusso1986@gmail.com&lt;/A&gt;&lt;SPAN&gt;' + '\n')&lt;/SPAN&gt;
f.write('Architecture : ' + platform.architecture()[0] + '\n')
f.write('Python EXE : ' + sys.executable + '\n')
f.write('Path to arcpy : ' + imp.find_module('arcpy')[1] + '\n' +'\n')
f.write('Start time was: ' + start + '\n')
end = (time.strftime('%x %X')) # End time
f.write('End time was: ' + end + '\n' + '\n')
for message in messageList:
&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(message)
&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write('\n' + '\n')
f.close()&lt;/PRE&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Sat, 11 Dec 2021 23:06:16 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530724#M41519</guid>
      <dc:creator>MatthewRusso</dc:creator>
      <dc:date>2021-12-11T23:06:16Z</dc:date>
    </item>
    <item>
      <title>Re: Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530725#M41520</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;The &lt;A href="https://www.python.org/dev/peps/pep-0008/" rel="nofollow noopener noreferrer" target="_blank"&gt;PEP8 Style Guide&lt;/A&gt; is a great place to start. Now that you a familiar with the syntax, the style guides will make more sense.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;From the start, the style guides recommend putting each &lt;A href="https://www.python.org/dev/peps/pep-0008/#imports" rel="nofollow noopener noreferrer" target="_blank"&gt;module you import&lt;/A&gt; on its own line. So instead of this&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;&lt;SPAN class="keyword" style="font-size: 12px; font-family: Consolas, 'Courier New', Courier, mono, serif; color: #006699;"&gt;import&lt;/SPAN&gt;&lt;SPAN style="font-size: 12px; font-family: Consolas, 'Courier New', Courier, mono, serif; color: #000000;"&gt; time, sys, platform, imp, arcpy&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;Do this&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;import arcpy
import imp
import platform
import sys
import time&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="https://www.python.org/dev/peps/pep-0008/#inline-comments" rel="nofollow noopener noreferrer" target="_blank"&gt;Inline comments&lt;/A&gt; are helpful but can be overdone, so be careful. They should also be separated from the code line by at least two spaces (you only have one).&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Consider the &lt;A href="https://www.python.org/dev/peps/pep-0008/#maximum-line-length" rel="nofollow noopener noreferrer" target="_blank"&gt;maximum line length&lt;/A&gt;. Super long lines of code are very hard (for a human) to interpret and arcpy functions are notorious for turning into monsters. Try declaring more of your function arguments as variables and take advantage of the multi-line capabilities within the parenthesis.&lt;/P&gt;&lt;P&gt;Instead of this&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;arcpy.SelectLayerByAttribute_management(outLayer, "NEW_SELECTION", ' "DCA1" = 80003 OR "DCA2" = 80003 OR "DCA3" = 80003 OR "DCA1" = 11006 OR "DCA2" = 11006 OR "DCA3" = 11006 ')&lt;/PRE&gt;&lt;P&gt;Do this&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;where_clause = ' "DCA1" = 80003 OR "DCA2" = 80003 OR "DCA3" = 80003 OR "DCA1" = 11006 OR "DCA2" = 11006 OR "DCA3" = 11006 '
arcpy.SelectLayerByAttribute_management(
&amp;nbsp;&amp;nbsp;&amp;nbsp; outLayer,
&amp;nbsp;&amp;nbsp;&amp;nbsp; "NEW_SELECTION",
&amp;nbsp;&amp;nbsp;&amp;nbsp; where_clause
)&lt;/PRE&gt;&lt;P&gt;Or you can take advantage of multiline strings and do something like this for the where clause. I used triple double quotes (""") but those are typically used for docstrings so I try to use triple single quotes ('''). However, the GeoNet forums do funny things with triple single quotes in Python syntax highlighting so I had to write this with triple double quotes.&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;where_clause = """
&amp;nbsp;&amp;nbsp;&amp;nbsp; "DCA1" = 80003
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA2" = 80003
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA3" = 80003
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA1" = 11006
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA2" = 11006
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA3" = 11006
"""&lt;/PRE&gt;&lt;P&gt;But I would go even further and actually improve the SQL for the where clause and do this&lt;/P&gt;&lt;PRE class="lia-code-sample line-numbers language-none"&gt;where_clause = """
&amp;nbsp;&amp;nbsp;&amp;nbsp; "DCA1" IN(8003,11006)
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA2" IN(8003,11006)
&amp;nbsp;&amp;nbsp;&amp;nbsp; OR "DCA3" IN(8003,11006)
"""&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;It may also help to declare some smaller local variables at the beginning of the code block it will be used in rather than everything at the beginning. Or you can use comments to group the variables by use, like "connections", "tables", "feature classes", etc.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;When opening files to read and write (like you've done at the end with the log file), it's better practice to use a &lt;A href="https://www.python.org/dev/peps/pep-0343/" rel="nofollow noopener noreferrer" target="_blank"&gt;with statement&lt;/A&gt; so the file is always closed, even if there was an error. If your current code errored after you opened the file and before you closed it, the file would not get closed.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Finally, a lot of Python IDEs style two types of comments differently: # and ##&lt;/P&gt;&lt;P&gt;I like to use the single hash comment (#) for the heading of a large block of code and the double hash (##) for headings under the main heading or for inline comments. I also try to put one line between the main blocks of code and no lines between code that is all together so you can visually group the major blocks of logic. If a block of code is too long to easily fit this style, then it might be better off written as a function and called from your main().&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I'm still learning Python myself and started just like you, Matthew. Please correct me if my assumptions are wrong! &lt;IMG src="https://community.esri.com/legacyfs/online/emoticons/happy.png" /&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Sat, 11 Dec 2021 23:06:19 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530725#M41520</guid>
      <dc:creator>BlakeTerhune</dc:creator>
      <dc:date>2021-12-11T23:06:19Z</dc:date>
    </item>
    <item>
      <title>Re: Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530726#M41521</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;A href="https://community.esri.com/migrated-users/48550"&gt;Blake T&lt;/A&gt;‌,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Thanks for the response, this is the exact information that I am looking for.&amp;nbsp; Right now I am at the point where I can get things to "work".&amp;nbsp; I want to get more in line with the right styles and methods of doing things. &lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The inline comments are mainly for the other people who may not have coding experience to help understand what is going on.&amp;nbsp; My personal version of this contains far less comments.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Also great information on the import situation.&amp;nbsp; I always wondered why most people did not use the multiple import method.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Thanks!&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 11 Feb 2015 21:07:18 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530726#M41521</guid>
      <dc:creator>MatthewRusso</dc:creator>
      <dc:date>2015-02-11T21:07:18Z</dc:date>
    </item>
    <item>
      <title>Re: Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530727#M41522</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Good suggestions by &lt;A href="https://community.esri.com/migrated-users/48550"&gt;Blake T&lt;/A&gt;‌.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Some more&amp;nbsp; (though not specifically for your script) can be found here: &lt;A href="https://community.esri.com/docs/DOC-1927"&gt;Some Python Snippets&lt;/A&gt; &lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 11 Feb 2015 21:11:08 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530727#M41522</guid>
      <dc:creator>XanderBakker</dc:creator>
      <dc:date>2015-02-11T21:11:08Z</dc:date>
    </item>
    <item>
      <title>Re: Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530728#M41523</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN&gt;Have you considered hiding all code from your users by using your script as a script tool? &lt;/SPAN&gt;&lt;A class="jive-link-external-small" href="http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//001500000006000000.htm" rel="nofollow" target="_blank"&gt;http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//001500000006000000.htm&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Then it's a matter of getting your users to enter parameters via the tool dialog, and accessing those parameters with arcpy.GetParameterAsText().&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 11 Feb 2015 21:38:45 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530728#M41523</guid>
      <dc:creator>DarrenWiens2</dc:creator>
      <dc:date>2015-02-11T21:38:45Z</dc:date>
    </item>
    <item>
      <title>Re: Writing better Python Code</title>
      <link>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530729#M41524</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Yes Darren,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;My orginal script was in a Python Toolbox.&amp;nbsp; This is my plan maybe later down the road but it seems like everytime the new data comes out, there is a change so I have to adjust something. &lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Matt&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 12 Feb 2015 13:15:26 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/writing-better-python-code/m-p/530729#M41524</guid>
      <dc:creator>MatthewRusso</dc:creator>
      <dc:date>2015-02-12T13:15:26Z</dc:date>
    </item>
  </channel>
</rss>

