How to make file paths configurable within an ArcGIS Python Add-In? - python

This might be a general programming question but since I am doing it from within an Add-In therefore asking here at GIS forum. I have a project folder with sub-folders containing several files on my hard disk which I read from within my Python Add-In, its hard coded e.g.:
dem = r'C:/project/raster/dem'
and Add-In is in
r'C:/project/Add-In'
folder. I tried doing '../raster/dem' to define path of input raster layer but it failed to read. Please suggest how can I make it generic so that if I move project folder to D drive then Add-In would still be able to read data.

You can reference materials that are located within the add-in, everything that's included within the 'Install' directory will be copied into the appropriate location within AssemblyCache. You can then reference this by doing something like:
local_path = os.path.abspath(os.path.basename(__file__))
raster_path = os.path.join(local_path, 'rasters')
And from there, treat raster_path as a nomral path.

You could read in a configuration file stored under the user's profile. Because ArcGIS add-ins overwrite themselves every time the host application is opened, you don't want to store user-specific configuration information inside the add-in itself.
The configuration file can be in any format you want (e.g. XML, plain text), but the ConfigParser class makes reading and writing to an INI-like file format easy.

Related

How to Open and Save Files in Parallel Directory Without Knowing Full Path

I am wondering if there is an easy way to access 'parallel' directories (See photo for what I am talking about... I don't know what else to call them, please correct me if they are called something else!) from a Python file without having to input the string path.
The basic structure I intend to use is shown in the picture. The structure will be used across different computers, so I need to avoid just typing in "C:\stuff_to_get_there\parent_directory\data\file.txt" because "C:\stuff_to_get_there" will not be the same on different computers.
I want to store the .py files in their own directory, then access the data files in data directory, and save figures to figures directory. I was thinking of trying os module but not sure if that's the correct way to go.
parent directory
scripts
.py files
figures
save files here
data
.txt files stored here
Thanks for any help!

naming and storing fileinformation for comparison

I am currently working on a script that automatically syncs files from the Documents and Picture directory with an USB stick that I use as sort of an "essentials backup". In practice, this should identify filenames and some information about them (like last time edited etc.) in the directories that I choose to sync.
If a file exists in one directory, but not in the other (i.e. it's on my computer but not on my USB drive), it should automatically copy that file to the USB as well. Likewise, if a file exists in both directories, but has different mod-times, it should replace the older with the newer one.
However, I have some issues with storing that information for the purpose of comparing those files. I initially thought about a file class, that stores all that information and through which I can compare objects with the same name.
Problem 1 with that approach is, that if I create an object, how do I name it? Do I name it like the file? I then would have to remove the file-extension like .txt or .py, because I'd run into trouble with my code. but I might have a notes.odt and a notes.jpg, which would be problem 2.
I am pretty new to Python, so my imagination is probably limited by my lack of knowledge. Any pointers on how I could make that work?

How to store Revit Add-in Settings with Python?

My Revit Add-in reads at some point a text file, that could be located anywhere. In my current implementation, the path to the text file is hardcoded. I'd like to avoid that, so that when I distribute the Add-in to other people, it doesn't simply crash.
Ideally I'd like to give them the ability of specifying their own location for that file on their computer, and that they don't need to re-specify it every time they re-launch the Add-in!
In other words, I'd like to store once and for all this information. And if you close and re-open Revit, the location is still stored somewhere when you re-use the Addin.
This question is actually similar to this one, except that I'd need a solution when developing in Python (pyRevit). Any help?
if you're developing you addon in pyRevit, then you can use the pyrevit.script module to get the configuration for that script.
Ask user for the file location (pyrevit.forms.save_file helps) and then save the file path in the script configuration. pyRevit handles this automatically and saves the information inside its master configuration file at %appdata%/pyRevit
from pyrevit import script
config = script.get_config()
config.filelocation = 'path/to/your/file'
script.save_config()
And then later, read the configuration like this:
from pyrevit import script
config = script.get_config()
print(config.filelocation)
# or to get the config safely
print(config.get_option('filelocation', None)
I implemented two other ways to store Revit add-in settings in the HoloLens Escape Path Waypoint JSON Exporter:
Store add-in option settings in XML using the .NET System.Configuration.ApplicationSettingsBase class
Store add-in option settings in JSON using custom solution and JavaScriptSerializer class
Both solutions are well suited for what you need.
Check them out in the ExportWaypointsJson GitHub repository.

can linux command line programs see python temporary files?

I have a simple web-server written using Python Twisted. Users can log in and use it to generate certain reports (pdf-format), specific to that user. The report is made by having a .tex template file where I replace certain content depending on user, including embedding user-specific graphs (.png or similar), then use the command line program pdflatex to generate the pdf.
Currently the graphs are saved in a tmp folder, and that path is then put into the .tex template before calling pdflatex. But this probably opens up a whole pile of problems when the number of users increases, so I want to use temporary files (tempfile module) instead of a real tmp folder. Is there any way I can make pdflatex see these temporary files? Or am I doing this the wrong way?
without any code it's hard to tell you how, but
Is there any way I can make pdflatex see these temporary files?
yes you can print the path to the temporary file by using a named temporary file:
>>> with tempfile.NamedTemporaryFile() as temp:
... print temp.name
...
/tmp/tmp7gjBHU
As commented you can use tempfile.NamedTemporaryFile. The problem is that this will be deleted once it is closed. That means you have to run pdflatex while the file is still referenced within python.
As an alternative way you could just save the picture with a randomly generated name. The tempfile is designed to allow you to create temporary files on various platforms in a consistent way. This is not what you need, since you'll always run the script on the same webserver I guess.
You could generate random file names using the uuid module:
import uuid
for i in xrange(3):
print(str(uuid.uuid4()))
The you save the pictures explictly using the random name and pass insert it into the tex-file.
After running pdflatex you explicitly have to delete the file, which is the drawback of that approach.

Python: Correct way to write to another directory within a package

Currently working with the following package structure:
/package
__init__.py
final.py
/write
__init__.py
write.py
/data
backup.txt
backup1.txt
backup2.txt
final.py imports write.py, which should be able to go back one directory and write a series of backup .txt files to /data.
final.py should be able to go into /data during another call and access the backup files, hence the need to save the information in /data.
I'm not sure this should be the correct hierarchy for a package file? How would /write create text files in a directory branch separate from itself without using absolute file paths in case the whole project file is moved, say onto a server.
Would it be wrong (once the backup.txt files are created) to add a retrieve.py to /data which returns the .txt files in some sort of data structure and make /data a package, or (2) should final.py directly enter /data and retrieve the text files.
IMO you shouldn't be writing into your packages. Set your code up so that you are writing to a data directory that is potentially outside your package. Numerous code deployment strategies assume that your code will be in a directory that is not normally writable. (E.g. if it is packaged for common linux distributions, the code will go into /usr/lib/python.../yourpackage/ and the data will be written to /var/lib/yourpackage, or something similar.)
Put your retrieve.py outside of .../data, possibly in a .../read directory, or alongside final.py, depending on the organization you need.
To write to an arbitrary location, just pass the full path to open. For example, assume that you store the path to your data directory in a constant:
DATA_PATH = '/var/lib/mypackage'
def backup():
f = open(os.path.join(DATA_PATH, 'backup.txt'), 'w')
f.write('some backup data...')
f.close()

Categories