A thread on GeoNet caused me to revisit an earlier post where I showed one option for documenting scripts as they were run. I didn’t include the generating script in that post since it was quite unwieldy. A slightly different and simpler, example is given here.
The scripts below show the generation of namespace within python as modules are imported. Also of equal importance, is how to cleanup after yourself when you are done a run and have no need for the variables generated.
The first script ... calling_script.py ... does just that. It is used to import a series of python modules including one user-created script ... import_this.py ... which contains a few useless functions.
<SPAN class="string token">"""
Script: calling_script.py
Author:
<A class="jive-link-email-small" href="mailto:Dan.Patterson@carleton.ca" rel="nofollow noopener noreferrer" target="_blank">Dan.Patterson@carleton.ca</A>
Requires: import_this.py script/module in the same path as this script
Returns: Some information about the imported module and this script
<SPAN>Reference: </SPAN><A class="jive-link-external-small" href="https://community.esri.com/external-link.jspa?url=https%3A%2F%2Fwww.python.org%2Fdev%2Fpeps%2Fpep-0257%2F" target="_blank">https://www.python.org/dev/peps/pep-0257/</A>
<SPAN> </SPAN><A class="jive-link-blog-small" data-containerid="2118" data-containertype="2020" data-objectid="1167" data-objecttype="37" href="https://community.esri.com/blogs/dan_patterson" target="_blank">https://community.esri.com/blogs/dan_patterson/2014/11/30</A>
/documenting-python-scripts-and-outputs-as-they-are-run
<SPAN> </SPAN><A class="jive-link-thread-small" data-containerid="2145" data-containertype="14" data-objectid="158590" data-objecttype="1" href="https://community.esri.com/thread/158590" target="_blank">https://community.esri.com/thread/158590</A>
"""</SPAN>
locals_in <SPAN class="operator token">=</SPAN> set<SPAN class="punctuation token">(</SPAN>locals<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>keys<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="comment token"># namespace at the beginning</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'\nMains script start... locals().keys ...\n{}'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>locals_in<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">import</SPAN> sys
<SPAN class="keyword token">import</SPAN> numpy <SPAN class="keyword token">as</SPAN> np
<SPAN class="keyword token">import</SPAN> arcpy
<SPAN class="keyword token">import</SPAN> import_this <SPAN class="comment token"># import the module in question</SPAN>
script <SPAN class="operator token">=</SPAN> sys<SPAN class="punctuation token">.</SPAN>argv<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN>
frmt <SPAN class="operator token">=</SPAN> <SPAN class="string token">"\nBack to main script...{}"</SPAN>
frmt <SPAN class="operator token">+=</SPAN> <SPAN class="string token">"\nimported module info:\n__doc__...{}__help__...\n{}"</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN>frmt<SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>script<SPAN class="punctuation token">,</SPAN> import_this<SPAN class="punctuation token">.</SPAN>__doc__<SPAN class="punctuation token">,</SPAN> import_this<SPAN class="punctuation token">.</SPAN>__help__<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">"\n-----------------------"</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">"Calling script doc...{}"</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN> __doc__ <SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
locals_out <SPAN class="operator token">=</SPAN> set<SPAN class="punctuation token">(</SPAN>locals<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>keys<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
diff <SPAN class="operator token">=</SPAN> sorted<SPAN class="punctuation token">(</SPAN>list<SPAN class="punctuation token">(</SPAN>locals_out<SPAN class="punctuation token">.</SPAN>difference<SPAN class="punctuation token">(</SPAN>locals_in<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Namespace change...\n{}'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>diff<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="comment token">#clean up</SPAN>
<SPAN class="keyword token">for</SPAN> i <SPAN class="keyword token">in</SPAN> diff<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">del</SPAN> locals<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">[</SPAN>i<SPAN class="punctuation token">]</SPAN>
<SPAN class="keyword token">del</SPAN> locals_out<SPAN class="punctuation token">,</SPAN> i<SPAN class="punctuation token">,</SPAN> diff
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'\nNamespace after cleanup...\n{}'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>locals<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>keys<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>In lines 13 and 14, the local namespace is obtained and printed prior performing the imports. Most of the imports are common ones used people programming for ArcMap. The ... import_this ... module is nothing more than a user written script which contains a few useless functions. That script can also be run in standalone mode so that you can see the difference in outputs.
The remainder of the calling_script, obtains the local namespace after imports, performs a difference in the before and after, then cleans out the namespace. Those lines can be commented out should you chose to keep access to the variables for command line use.
The module/script being imported is as follows:
<SPAN class="string token">"""
Script: import_this.py
<SPAN>Author: </SPAN><A class="jive-link-email-small" href="mailto:Dan.Patterson@carleton.ca" rel="nofollow noopener noreferrer" target="_blank">Dan.Patterson@carleton.ca</A>
Requires: absolutely nothing
Returns: see Requirements
Purpose: imports, namespace and doc strings
(and recursion in Returns-Requires)
"""</SPAN>
<SPAN class="keyword token">import</SPAN> sys
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">do_squat</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="string token">""""Hello...I am 'do_squat' the function in import_this.py"
"""</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN>do_squat<SPAN class="punctuation token">.</SPAN>__doc__<SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">do_stuff</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="string token">"""Hi... I am 'do_stuff' a function in 'import_this.py'\n"""</SPAN>
done <SPAN class="operator token">=</SPAN> do_stuff<SPAN class="punctuation token">.</SPAN>__doc__ <SPAN class="operator token">+</SPAN> __help__
<SPAN class="keyword token">return</SPAN> done
<SPAN class="keyword token">if</SPAN> __name__ <SPAN class="operator token">==</SPAN> <SPAN class="string token">'__main__'</SPAN><SPAN class="punctuation token">:</SPAN>
do_squat<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN>
__help__ <SPAN class="operator token">=</SPAN> <SPAN class="string token">" I am being imported"</SPAN>
done <SPAN class="operator token">=</SPAN> do_stuff<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">"\nimport_this.py ... says...\n{}"</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>done<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>The output after a run of the calling script records the document information for the modules and the functions contained within the imported module.
Mains script start... locals().keys ...
set(['__builtins__', '__file__', 'pywin', '__package__', '__name__', '__doc__'])
import_this.py ... says...
Hi... I am 'do_stuff' a function in 'import_this.py'
I am being imported
Back to main script...D:\Temp\calling_script.py
imported module info:
__doc__...
Script: import_this.py
Author:
Dan.Patterson@carleton.ca
Requires: absolutely nothing
Returns: see Requirements
Purpose: imports, namespace and doc strings
(and recursion in Returns-Requires)
__help__...
I am being imported
-----------------------
Calling script doc...
Script: calling_script.py
Author:
Dan.Patterson@carleton.ca
Requires: import_this.py script/module in the same path as this script
Returns: Some information about the imported module and this script
Reference:
https://www.python.org/dev/peps/pep-0257/
https://community.esri.com/blogs/dan_patterson/2014/11/30
/documenting-python-scripts-and-outputs-as-they-are-run
https://community.esri.com/thread/158590
Namespace change...
['arcgis', 'arcpy', 'datetime', 'frmt', 'import_this', 'locals_in', 'math', 'np',
'script', 'sys', 'time']
Namespace after cleanup...
['__builtins__', '__file__', 'pywin', '__package__', '__name__', '__doc__']<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
If you follow the sequences within the scripts and the outputs you can get a sense where you might want to include such information.