__file__ is missing

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

Are you on the server or on the client?

I’m on the server side.

Hi @icarmi,

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!

That’s too bad… it would have been much more convenient.

Is there a way to get access to the in-memory virtual file handler?

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

I can then call it:

local_path = get_data_path('some_file.csv')

When you are running the code locally, don’t forget that you can very easily use the Uplink to pull the data file from the Data Table too!

Interesting! I’ll check it out, thanks!