【问题标题】:What is the correct way to generate a json from file in GoogleAppEngine?从 GoogleAppEngine 中的文件生成 json 的正确方法是什么?
【发布时间】:2009-08-13 19:19:05
【问题描述】:

我是 python 和 GAE 的新手,谁能提供一些帮助/示例代码来完成以下简单任务?我设法读取了一个简单的文件并将其作为网页输出,但我需要一些稍微复杂的逻辑。这是伪代码:

  open file;
  for each line in file {
    store first line as album title;
    for each song read {
      store first line as song title;
      store second line as song URL;
    }
  }
  Output the read in data as a json;

文件格式是这样的

专辑标题 1
歌曲 1 标题
歌曲 1 网址
歌曲 2 标题
歌曲 2 网址

专辑标题 2
歌曲 1 标题
歌曲 1 网址
歌曲 2标题
歌曲 2 网址
..

【问题讨论】:

  • 您使用的是什么版本的 Python?这将决定您是否可以使用内置的 json 库。
  • 你看过“from django.utils import simplejson”吗?
  • @Trypich,因为 OP 不止一次地非常明确地提到了 GoogleAppEngine,你认为他们可能会使用什么版本的 Python,除了 2.5?所以,没有内置的 json,但当然正如@Ethan 所说,这并不重要,因为他可以使用来自 django 的那个。此外,打印并不是 GAE 应用程序通常的输出方式,response.out.write 更有可能是 OP 想要的。
  • @Alex 是的 - 我没有大量的 GAE 经验。感谢您指出了这一点。此外,我认为我会将打印作为“现在对此做点什么”的占位符。

标签: python google-app-engine file-io


【解决方案1】:

这是一个基于生成器的解决方案,具有一些不错的功能:

  • 允许文本文件中专辑之间有多个空行
  • 允许文本文件中的前导/尾随空行
  • 一次只使用一张专辑的内存
  • 演示了很多你可以用 Python 做的整洁的事情 :)

albums.txt

Album title1
song1 title
song1 url
song2 title
song2 url

Album title2
song1 title
song1 url
song2 title
song2 url

代码

from django.utils import simplejson

def gen_groups(lines):
   """ Returns contiguous groups of lines in a file """

   group = []

   for line in lines:
      line = line.strip()
      if not line and group:
         yield group
         group = []
      elif line:
         group.append(line)


def gen_albums(groups):
   """ Given groups of lines in an album file, returns albums  """

   for group in groups:
      title    = group.pop(0)
      songinfo = zip(*[iter(group)]*2)
      songs    = [dict(title=title,url=url) for title,url in songinfo]
      album    = dict(title=title, songs=songs)

      yield album


input = open('albums.txt')
groups = gen_groups(input)
albums = gen_albums(groups)

print simplejson.dumps(list(albums))

输出

[{"songs": [{"url": "song1 url", "title": "song1 title"}, {"url": "song2 url", "title": "song2 title"}], "title": "song2
title"},
{"songs": [{"url": "song1 url", "title": "song1 title"}, {"url": "song2 url", "title": "song2 title"}], "title": "song2
title"}]

然后可以像这样在 Javascript 中访问专辑信息:

var url = albums[1].songs[0].url;

最后,这里是关于 tricky zip line 的注释。

【讨论】:

  • 哇,赞了,我必须导入任何东西才能让 json.dumps 在 GAE 中工作吗?
  • 是的,刚刚注意到 GAE 使用 Python 2.5,这意味着您必须导入 simplejson,它很好地包含在 django 中,它包含在 GAE 中:)。我相应地更改了我的代码 - 应该按原样工作。
  • @erotsppa - 关于此解决方案的说明:它确实要求输入文件格式正确,因为始终存在完整的歌曲/网址对。
  • 我刚试过你的代码,我得到一个 NameError: global name 'gen_groups' is not defined。我把你的两个方法放在我的类 MainHandler 中。这是正确的吗?
  • @erotsppa - 将这两种方法放在全局范围内可能会解决您的问题,但您可能希望在 Python 中研究范围。您还可以创建一个新模块并在其中转储这些方法,然后像导入其他模块一样导入该模块。
【解决方案2】:
from django.utils import simplejson

def albums(f):
  "" yields lists of strings which are the
     stripped lines for an album (blocks of
     nonblank lines separated by blocks of
     blank ones.
  """
  while True:
    # skip leading blank lines if any
    for line in f:
      if not line: return
      line = line.strip()
      if line: break
    result = [line]
    # read up to next blank line or EOF
    for line in f:
      if not line:
        yield result
        return
      line = line.strip()
      if not line: break
      result.append(line)
    yield result

def songs(album):
  """ yields lists of 2 lines, one list per song.
  """
  for i in xrange(1, len(album), 2):
    yield (album[i:i+2] + ['??'])[:2]

result = dict()
f = open('thefile.txt')
for albumlines in albums(f):
  current = result[albumlines[0]] = []
  for songlines in songs(albumlines):
    current.append( {
      'songtitle': songlines[0],
      'songurl': songlines[1]
    } )

response.out.write(simplejson.dumps(result))

【讨论】:

    猜你喜欢
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2020-11-22
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多