我如何制作一个Python包来为一个使用Flask的网站提供服务呢?

2024-09-26 22:51:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经编写了一个Python包^{}(如果您想尝试的话,请参见installation instructions),它在执行时为网站提供服务

$ hwrt serve
2014-12-04 20:27:07,182 INFO  * Running on http://127.0.0.1:5000/
2014-12-04 20:27:07,183 INFO  * Restarting with reloader

我想让它在http://www.pythonanywhere.com上运行,但是当我在那里启动它时

^{pr2}$

我只在文件中找到这个:

Flask

never use app.run(), it will break your webapp. Just import the app into your wsgi file...

通过搜索wsgi文件,我找到了mod_wsgi (Apache)。但是,我不明白如何调整我当前的极简烧瓶应用程序来处理这个问题。当前,hwrt serve背后的脚本是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Start a webserver which can record the data and work as a classifier."""

import pkg_resources
from flask import Flask, request, render_template
from flask_bootstrap import Bootstrap
import os
import json

# hwrt modules
import hwrt
import hwrt.utils as utils


def show_results(results, n=10):
    """Show the TOP n results of a classification."""
    import nntoolkit
    classification = nntoolkit.evaluate.show_results(results, n)
    return "<pre>" + classification.replace("\n", "<br/>") + "</pre>"

# configuration
DEBUG = True

template_path = pkg_resources.resource_filename('hwrt', 'templates/')

# create our little application :)
app = Flask(__name__, template_folder=template_path)
Bootstrap(app)
app.config.from_object(__name__)


@app.route('/', methods=['POST', 'GET'])
def show_entries():
    heartbeat = request.args.get('heartbeat', '')
    return heartbeat


@app.route('/interactive', methods=['POST', 'GET'])
def interactive():
    if request.method == 'POST':
        raw_data_json = request.form['drawnJSON']
        # TODO: Check recording
        # TODO: Submit recorded json to database
        # Classify
        model_path = pkg_resources.resource_filename('hwrt', 'misc/')
        model = os.path.join(model_path, "model.tar")
        print(model)
        results = utils.evaluate_model_single_recording(model, raw_data_json)
        # Show classification page
        page = show_results(results, n=10)
        page += '<a href="../interactive">back</a>'
        return page
    else:
        # Page where the user can enter a recording
        return render_template('canvas.html')


def get_json_result(results, n=10):
    s = []
    for res in results[:min(len(results), n)]:
        s.append({res['semantics']: res['probability']})
    return json.dumps(s)


@app.route('/worker', methods=['POST', 'GET'])
def worker():
    # Test with
    # wget --post-data 'classify=%5B%5B%7B%22x%22%3A334%2C%22y%22%3A407%2C%22time%22%3A1417704378719%7D%5D%5D' http://127.0.0.1:5000/worker
    if request.method == 'POST':
        raw_data_json = request.form['classify']
        # TODO: Check recording
        # TODO: Submit recorded json to database
        # Classify
        model_path = pkg_resources.resource_filename('hwrt', 'misc/')
        model = os.path.join(model_path, "model.tar")
        results = utils.evaluate_model_single_recording(model, raw_data_json)
        return get_json_result(results, n=10)
    else:
        # Page where the user can enter a recording
        return "Classification Worker (Version %s)" % hwrt.__version__


def get_parser():
    """Return the parser object for this script."""
    from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
    parser = ArgumentParser(description=__doc__,
                            formatter_class=ArgumentDefaultsHelpFormatter)
    return parser


def main():
    app.run()

if __name__ == '__main__':
    main()

Tags: thepathimportjsonappdatamodelreturn
2条回答

好吧,对于你的问题,一个不那么合理的答案是关于mod\wsgi如何与你的应用程序接口。典型的flask应用程序如下所示:

from flask import Flask
app = Flask(__name__)

app.route("/")
def hello():
    return "Holy moly that tunnel was bright.. said Bit to NIC"

if __name__ == "__main__":
    app.run()

不幸的是,Apache无法知道如何处理这个问题(尽管应用程序可以自己运行得很好)。为了让app和Apache更好地结合在一起,我们将使用mod wsgi。Mod_WSGI所做的对我们很重要,它提供了一个已知的接口(一个名为WSGI的文件类型),它将包装我们的应用程序并对其进行初始化,这样我们就可以通过Apache为它提供服务。在

我假设您使用的是python虚拟环境,但是如果您没有使用,您可以在下面的说明中省略处理这个问题的步骤。如果您想知道虚拟环境为什么这么好,feel free read about the python ecosystem。在

另外-您可以包含一个额外的标志(假设您将wsgi作为守护进程运行),以便在您touch或更改wsgi文件时自动重新加载守护进程。这在开发和调试期间非常有用,因此我将在下面介绍。在

不管怎样,我们开始吧。我将把这个分解成下面的步骤。在

配置Apache mod

  1. 在Apache中启用mod\u wsgi:
    • sudo apt-get install libapache2-mod-wsgi
  2. 编辑您的/etc/apache2/sites-available/<yoursite>.conf。在

    <VirtualHost interface:port>
         WSGIDaemonProcess yourapp user=someUser processes=2 threads=15
         WSGIProcessGroup yourapp
    
         # In this case / refers to whatever relative URL path hosts flask
         WSGIScriptAlias / /absolute/path/to/yourapp.wsgi
    
         <Directory /path/to/your/main/py/file/ >
             # Use good judgement here when server hardening, this assumes dev env
             Order allow,deny
             Allow from all
             Require all granted
             #The below enables 'auto-reload' of WSGI
             WSGIScriptReloading On
         </Directory>
    
         # If you want to serve static files as well and bypass flask in those cases
         Alias /relative/url/to/static/content/
         <Directory /absolute/path/to/static/root/directory/>
             Order allow,deny
             Allow from all
         </Directory>
    </VirtualHost>
    
  3. 创建您的你的app.wsgi文件并放在适当的地方:小心文件权限!

    #!/usr/bin/python
    import sys
    import logging
    
    # Activate virtual environment.
    # If you are not using venv, skip this.
    # But you really should be using it!
    activate_this = "/path/to/venv/bin/activate_this.py"
    execfile(activate_this, dict(__file__=activate_this))
    
    # Handle logging 
    logging.basicConfig(stream=sys.stderr)
    
    sys.path.insert(0, "/path/to/your/main/py/file/")
    from YourMainPyFileName import app as application
    application.secret_key = "your_secret_key"
    
  4. 重新加载Apache并解决问题。我可能每隔几周就为一个不同的项目或想法设立这个项目。。。从零开始做的时候,我通常要修理一件或另一件事。但不要绝望!Flask has great documentation on this

一旦你完成了所有这些,你应该在一个地方,烧瓶自己运行。上面的示例flask应用程序是我在设置此程序时用来验证一切工作正常的实际代码。在


这里留着,以防有用,但与问题没有直接关系…

这里的答案是使用x-send-file。这充分利用了让Apache做它擅长的事情(提供静态内容),同时首先让flask(或其他python框架)先做它的工作。我经常这样做是为了让flask在单页web应用程序中处理我的auth层,到目前为止,我对结果很满意。在

这样做需要两件事:

首先-在Apache2上启用xsendfilesudo apt-get install libapache2-mod-xsendfile。在

第二步-更改apache2配置,以便允许x-send-file头:

{并在cd3>中添加文件}。。。在

  • XSendFile On
  • XSendFilePath /path/to/static/directory

这可以在<Virtualhost></Virtualhost>标记的顶层输入。

别忘了重启Apache sudo service apache2 restart。在

最后-配置你的flask应用程序在你的应用程序副本文件:

app.user_x_sendfile = True

注意:必须在应用程序初始化后完成。因此也可以作为初始化参数传递。

Flask has documentation on this(节选如下):

use_x_sendfile

Enable this if you want to use the X-Sendfile feature. Keep in mind that the server has to support this. This only affects files sent with the send_file() method.

New in version 0.2.

This attribute can also be configured from the config with the USE_X_SENDFILE configuration key. Defaults to False.

我也遇到过类似的问题。连接被拒绝,甚至无法telnet localhost 5000。在

原来有一个端口.conf我必须添加的文件听5000

快乐的日子。在

相关问题 更多 >

    热门问题