39

Is it possible to open a file on GAE just to read its contents and get the last modified tag?

I get a IOError: [Errno 13] file not accessible: I know that i cannot delete or update but i believe reading should be possible Has anyone faced a similar problem?

os.stat(f,'r').st_mtim
Abizern
  • 146,289
  • 39
  • 203
  • 257
PanosJee
  • 3,866
  • 6
  • 36
  • 49
  • Try using a relative directory and make sure it is in your app, not the root – Romain Hippeau Apr 13 '10 at 14:26
  • i ve already tried that when i have a path problem i get otehr Errno 2 – PanosJee Apr 13 '10 at 14:34
  • A Googler responded and told me that you cannot read files marked as static. But that s my problem as i want to open my JS/CSS files. I ll let you know if i find smth – PanosJee Apr 13 '10 at 14:50
  • Please don't crosspost to the groups and SO - pick one, unless you don't get answers. – Nick Johnson Apr 14 '10 at 10:36
  • You can read the files if you're not using them as static files. If you're using them as static files you can access them by using the application_readable. But if you don't probably the problem is that the file system is case sensitive. – Victor Naranjo Feb 06 '15 at 22:39

6 Answers6

54

You've probably declared the file as static in app.yaml. Static files are not available to your application; if you need to serve them both as static files and read them as application files, you'll need to include 2 copies in your project (ideally using symlinks, so you don't actually have to maintain an actual copy.)

Update Nov 2014:

As suggested in the comments, you can now do this with the application_readable flag:

application_readable

Optional. By default, files declared in static file handlers are uploaded as static data and are only served to end users, they cannot be read by an application. If this field is set to true, the files are also uploaded as code data so your application can read them. Both uploads are charged against your code and static data storage resource quotas.

See https://cloud.google.com/appengine/docs/python/config/appconfig#Static_Directory_Handlers

Wooble
  • 87,717
  • 12
  • 108
  • 131
  • how can i use symblinks in GAE environment ? – PanosJee Apr 15 '10 at 14:14
  • 7
    You create the symlinks in your local copy; the files will actually be copied twice to App Engine: once to the static file servers and once to the application servers. You can also include external packages by symlinking your local copies to your application directory rather than copying the whole package to each project that uses it. – Wooble Apr 15 '10 at 17:31
  • that was an awesome tip! thanx! – PanosJee Apr 16 '10 at 15:46
  • +1 , coming from your fine remark to this question (http://stackoverflow.com/questions/15365046/python-removing-pos-tags-from-a-txt-file#comment21717089_15365046) – eyquem Mar 12 '13 at 19:07
  • 10
    actually now you can use ``application_readable: true`, consider updating your answer, see https://developers.google.com/appengine/docs/python/config/appconfig#Static_Directory_Handlers – proppy May 30 '13 at 08:23
  • 4
    This doesn't look like an answer on how to "Read a file on App Engine with Python?" – Jonny Sep 02 '13 at 09:31
  • Thanks Wooble for accepting and also tidying my edit - my first one on SO. Your orig answer is also insightful and worth remembering in case it comes in useful. – sifriday Nov 04 '14 at 17:52
  • 1
    +1 In my app.yaml - url: /resources/* static_dir: resources application_readable: true – Raunak May 16 '15 at 11:13
12

You can read files, but they're on Goooogle's wacky GAE filesystem so you have to use a relative path. I just whipped up a quick app with a main.py file and test.txt in the same folder. Don't forget the 'e' on st_mtime.

import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util


class MainHandler(webapp.RequestHandler):

  def get(self):
    path = os.path.join(os.path.split(__file__)[0], 'test.txt')

    self.response.out.write(os.stat(path).st_mtime)


def main():
  application = webapp.WSGIApplication([('/', MainHandler)],
                                       debug=True)
  util.run_wsgi_app(application)


if __name__ == '__main__':
  main()
MStodd
  • 4,716
  • 3
  • 30
  • 50
6

+1 for the new "application_readable: true" feature. Before using this new feature I did run into an issue with GAEs' "wacky" file system while getting the NLP Montylingua to import.

Issue: Monty uses the open(filename,'rb') and a file pointer to file_ptr.read() in bytes from the static files. My implementation worked on my local windows system but failed upon deployment!

The fix: Specify the expected bytes to read file_ptr.read(4) #4 binary bytes

Appears to be something related to the 64 bit GAE server wanting to read in more (8 by default) bytes. Anyways, took a while to find that issue. Montylingua loads now.

jonincanada
  • 417
  • 5
  • 5
2

I came up strange but working solution :) Jinja :)

Serving static files directly sometimes become a headache with GAE. Possible trade-off from performance let you move straigh forward with Jinja

- url: /posts/(.*\.(md|mdown|markdown)) 
  mime_type: text/plain
  static_files: static/posts/\1
  upload: posts/(.*\.(md|mdown|markdown))



from jinja2 import Environment
from jinja2.loaders import FileSystemLoader
posts = Environment(loader=FileSystemLoader('static/posts/')) # Note that we use static_files folder defined in app.yaml
post = posts.get_template('2013-11-13.markdown')

import markdown2 # Does not need of course

class Main(webapp2.RequestHandler):

    def get ( self ):
        self.response.headers[ 'Content-Type' ] = 'text/html'

        self.response.write ( markdown2.markdown( post.render()) )  # Jinja + Markdown Render function

Did you get it ;) I tested and It worked.

guneysus
  • 6,203
  • 2
  • 45
  • 47
1

With webapp2, supposing you have pages/index.html at the same path as main.py:

#!/usr/bin/env python

import webapp2, os

class MainHandler(webapp2.RequestHandler):
    def get(self):
        path = os.path.join(os.path.split(__file__)[0], 'pages/index.html')
        with open(path, 'r') as f:
            page_content = f.read()
        self.response.write(page_content)

app = webapp2.WSGIApplication([
    ('/', MainHandler)
], debug=True)
Ivan Chaer
  • 6,980
  • 1
  • 38
  • 48
0

I can't see an answer for when the file hasn't been marked as static, and you're trying to read it in mode 'rt'; apparently that doesn't work. You can however open files just fine in mode 'rb', or just plain 'r'. (I wasted about 10 minutes on that 't'.)