简体   繁体   中英

How to read and write files with Appengine in Python?

I'm new at appengine and i need your help.

The javascript i want to display generates a graph.

import webapp2

MAIN_PAGE_HTML1 = """\
<html>
<body>
<script>
  #My script comes here
  var graph = new Graph();
  graph.addNodes('a', 'b');
  graph.addEdges(['a', 'b']);
  #...
</script>
</body>
</html>
"""
class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.write(MAIN_PAGE_HTML1)


app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

My idea was to store the main html in a file and read it if the RequestHandler is called and modify it when i post new graph elements from a client. I can't do this, because appengine doesn't allow standard file operations.

What is the easiest way to make it work?

App Engine lets you read files just fine, just not write to them. Among the many alternatives to plain files that you can use if you need read/write functionality, the best two are usually: (A) the App Engine data store, for "files" of modest to moderate size; (B) Google Cloud Storage, for "files" that can potentially be quite large.

Your use case seems to call for the former -- ie, the datastore -- so I'll focus on that possibility.

Define a model class for entities representing HTML you want to send in your response -- usually such "models" are best kept in a separate model.py file, to be imported from others of your Python files, but that's an issue of proper code organization, not of functionality. For the latter, whatever file you place it in, your code will be somewhat like:

from google.appengine.ext import ndb

class Page(ndb.Model):
    name = ndb.StringProperty()
    html = ndb.TextProperty()

When you need to get a page by a certain name, your code will be something like:

page = Page.query(Page.name == the_name).get()
if page is None:
    page = Page(name=the_name, html=MAIN_PAGE_HTML1)
    page.put()

and to set new, modified html content on an existing page page previously fetched, just

page.html = new_html_content
page.put()

The put calls return a key which you may want to save (for example in memcache ) if you want "strong consistency" (since key.get() is guaranteed to fetch the latest updated content, while getting from a query, without other precautions, might get a previously saved version of the data -- it only exhibits eventual consistency, not "immediate" updates).

But it's hard to be more specific in offering advice about how you should best use the datastore without knowing much, much more about your exact requirements -- how do you determine exactly what page to display and/or update (that would be given by the name property in my example code, while it would have been given by the filename if you could have ordinary read/write files as you wished), what are your consistency (immediacy of updates) requirements, and so forth.

(For most use cases one could infer from your incomplete specs, I'd probably use the name , that here I have modeled as a property, instead as an id , part of a key -- but, I'm trying to keep things simple to match what little you have expressed about your specs).

Note that in this approach the whole html content is re-written each time you want to change it -- the same goes for the main alternative (suggested for potentially much larger files), Google Cloud Storage: no actual "incremental updates", just complete re-writes to affect any change to a "file"'s contents.

That's the main difference between GCS and a common filesystem (while the datastore also offers much more functionality on top, such as queries and ordering of entities -- we're just not using any of that extra functionality here because you're asking just for filesystem-like behavior).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM