What I’m trying to do:
Access a data file that is stored in my source code. (In the server code)
What I’ve tried and what’s not working:
In Python, I can usually access the __file__ attribute to know where my code is located, and then access files in the source code. It’s not working for me here, is there an alternative way to access files in the source folder?
Code Sample:
source_path = __file__
Is generating the following error:
ErrorLoadingUserCode: Error loading user code: name '__file__' is not defined
You can’t directly access files from your source code, because they don’t really exist - your Python source code is sent into a worker process and loaded directly from memory. If you have a data file, the best way to access it is to store it in a Media column of a Data Table, then load that in your code. I hope that helps!
My problem is that I need to run the code (at least the core parts of it) both locally on my computer, and on anvil.works servers.
So my compromise – not perfect – is to save two copies of the data files, once in the filesystem (git), and once in the database as @daviesian suggested.
I then wrote a utility function that checks if I’m running locally or on anvil.works servers, and then sets and the file properly:
from scriptine import path
def get_data_path(file_name):
from local import data # module containing media files
if hasattr(data, '__path__') and len(data.__path__) > 0: # if running locally, then can load the files directly
return path(data.__path__[0]).joinpath(file_name)
# if running on server, need to access files in DB, and create temporary files
from anvil.tables import app_tables
tmp_folder = path('/tmp/data')
tmp_folder.ensure_dir()
data_path = tmp_folder.joinpath(file_name)
if data_path.exists():
return data_path
rows = list(app_tables.files.search(file_name=file_name))
if len(rows) != 1:
raise KeyError(file_name)
row = rows[0]
media_object = row['content']
with open(data_path, 'wb') as f:
f.write(media_object.get_bytes())
return data_path