我正在尝试使用python flask框架构建一个静态博客生成器,并且我遇到了问题。目标是使用Frozen-Flask将我的Flask应用程序冻结为一组静态文件,以便我可以将文件推送到Github Pages。 python脚本工作正常但是当我在终端中输入构建命令时会出现问题。
请允许我详细说明以下步骤:
命令行输入:
python generator.py build
命令行输出:
Traceback (most recent call last):
File "generator.py", line 152, in <module>
freezer.freeze()
File "/home/chris/.virtualenvs/blog/local/lib/python2.7/site-packages/flask_frozen/__init__.py", line 166, in freeze
new_filename = self._build_one(url)
File "/home/chris/.virtualenvs/blog/local/lib/python2.7/site-packages/flask_frozen/__init__.py", line 280, in _build_one
% (response.status, url))
ValueError: Unexpected status '500 INTERNAL SERVER ERROR' on URL /feed.atom
我检查了ValueError的python文档,看看它是什么意思。
异常 ValueError
当内置操作或函数接收到参数时引发 具有正确的类型但价值不合适,情况如此 没有由更准确的异常描述,例如IndexError。
以下是终端输出中提到的python脚本的代码行:
@app.route('/feed.atom')
def feed():
feed = AtomFeed('Recent Articles',
feed_url=request.url,
url=request.url_root)
posts = blog.posts[:10]
title = lambda p: '%s: %s' % (p.title, p.subtitle) if hasattr(p, 'subtitle') else p.title
for post in posts:
feed.add(title(post),
unicode(post.html),
content_type='html',
author=post.author.name,
url=post.url(_external=True),
updated=post.date,
published=post.date)
return feed.get_response()
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'build':
freezer.freeze()
else:
post_files = [post.filepath for post in blog.posts]
app.run(port=8000, debug=True, extra_files=post_files)
如果您需要查看整个python脚本:
import os
import sys
import collections
from flask import Flask, render_template, url_for, abort, request
from flask.ext.frozen import Freezer
from werkzeug import cached_property
from werkzeug.contrib.atom import AtomFeed
import markdown
import yaml
FREEZER_BASE_URL = 'http://example.com'
FREEZER_DESTINATION_IGNORE = ['.git*', 'CNAME']
DOMAIN = 'example.com'
POSTS_FILE_EXTENSION = '.md'
class SortedDict(collections.MutableMapping):
def __init__(self, items=None, key=None, reverse=False):
self._items = {}
self._keys = []
if key:
self._key_fn = lambda k: key(self._items[k])
else:
self._key_fn = lambda k: self._items[k]
self._reverse = reverse
if items is not None:
self.update(items)
def __getitem__(self, key):
return self._items[key]
def __setitem__(self, key, value):
self._items[key] = value
if key not in self._keys:
self._keys.append(key)
self._keys.sort(key=self._key_fn, reverse=self._reverse)
def __delitem__(self, key):
self._items.pop(key)
self._keys.remove(key)
def __len__(self):
return len(self._keys)
def __iter__(self):
for key in self._keys:
yield key
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._items)
class Blog(object):
def __init__(self, app, root_dir='', file_ext=None):
self.root_dir = root_dir
self.file_ext = file_ext if file_ext is not None else app.config['POSTS_FILE_EXTENSION']
self._app = app
self._cache = SortedDict(key=lambda p: p.date, reverse=True)
self._initialize_cache()
@property
def posts(self):
if self._app.debug:
return self._cache.values()
else:
return [post for post in self._cache.values() if post.published]
def get_post_or_404(self, path):
"""Returns the Post object for the given path or raises a NotFound exception
"""
try:
return self._cache[path]
except KeyError:
abort(404)
def _initialize_cache(self):
"""Walks the root directory and adds all posts to the cache
"""
for (root, dirpaths, filepaths) in os.walk(self.root_dir):
for filepath in filepaths:
filename, ext = os.path.splitext(filepath)
if ext == self.file_ext:
path = os.path.join(root, filepath).replace(self.root_dir, '')
post = Post(path, root_dir=self.root_dir)
self._cache[post.urlpath] = post
class Post(object):
def __init__(self, path, root_dir=''):
self.urlpath = os.path.splitext(path.strip('/'))[0]
self.filepath = os.path.join(root_dir, path.strip('/'))
self.published = False
self._initialize_metadata()
@cached_property
def html(self):
with open(self.filepath, 'r') as fin:
content = fin.read().split('\n\n', 1)[1].strip()
return markdown.markdown(content, extensions=['codehilite'])
def url(self, _external=False):
return url_for('post', path=self.urlpath, _external=_external)
def _initialize_metadata(self):
content = ''
with open(self.filepath, 'r') as fin:
for line in fin:
if not line.strip():
break
content += line
self.__dict__.update(yaml.load(content))
app = Flask(__name__)
app.config.from_object(__name__)
blog = Blog(app, root_dir='posts')
freezer = Freezer(app)
@app.template_filter('date')
def format_date(value, format='%B %d, %Y'):
return value.strftime(format)
@app.route('/')
def index():
return render_template('index.html', posts=blog.posts)
@app.route('/blog/<path:path>/')
def post(path):
post = blog.get_post_or_404(path)
return render_template('post.html', post=post)
@app.route('/feed.atom')
def feed():
feed = AtomFeed('Recent Articles',
feed_url=request.url,
url=request.url_root)
posts = blog.posts[:10]
title = lambda p: '%s: %s' % (p.title, p.subtitle) if hasattr(p, 'subtitle') else p.title
for post in posts:
feed.add(title(post),
unicode(post.html),
content_type='html',
author=post.author.name,
url=post.url(_external=True),
updated=post.date,
published=post.date)
return feed.get_response()
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'build':
freezer.freeze()
else:
post_files = [post.filepath for post in blog.posts]
app.run(port=8000, debug=True, extra_files=post_files)
对于烧瓶来说,我还是个新手,所以我不完全确定如何解决这个问题。如果有人可以提供帮助,我将不胜感激。如果您需要更多信息,请与我们联系;我试图尽可能详细。
由于
答案 0 :(得分:0)
Flask-Frozen正在提升ValueError
,因为您的/feed.xml
端点返回500,内部服务器错误,而不是200,成功响应。 Flask-Frozen假设您不想保存400或500级错误的结果,并引发错误,以便您可以查看根本问题。
要查看错误,请在浏览器中访问/feed.xml
,看看错误响应是什么。