Python Flask应用程序在本地运行,但在Heroku上托管时返回AttributeError

如何解决Python Flask应用程序在本地运行,但在Heroku上托管时返回AttributeError

我正在开发大学申请。 该Web应用程序通过joblib加载给定模型,并且为了工作,使用了FlexibleScaler类:

flexible.py

from sklearn.preprocessing import MinMaxScaler,StandardScaler,PowerTransformer,MaxAbsScaler,RobustScaler,normalizer
from sklearn.base import BaseEstimator,TransformerMixin

class FlexibleScaler(BaseEstimator,TransformerMixin):
    def __init__(self,scaler=None):
        self.scaler = scaler
        self.check = False


    def __assign_scaler(self):
        if self.scaler == 'min-max':
            self.method = MinMaxScaler()
        elif self.scaler == 'standard':
            self.method = StandardScaler()
        elif self.scaler == 'yeo-johnson':
            self.method = PowerTransformer(method='yeo-johnson')
        elif self.scaler == 'Box-cox':
            self.method = PowerTransformer(method='Box-cox')
        elif self.scaler == 'max-abs':
            self.method = MaxAbsScaler()
        elif self.scaler == 'robust':
            self.method = RobustScaler()
        elif self.scaler == 'normalize':
            self.method = normalizer()
        else:
            self.method = None
        self.check = True

    def fit_transform(self,X,y=None,**fit_params):
        if not self.check:
            self.__assign_scaler()
        if self.method is None:
            return X
        return self.method.fit_transform(X,y,**fit_params)

    def fit(self,X):
        if not self.check:
            self.__assign_scaler()
        if self.method is None:
            return X
        self.method.fit(X)

    def transform(self,X):
        if not self.check:
            self.__assign_scaler()
        if self.method is None:
            return X
        return self.method.transform(X)

flask_start.py

from flask import Flask,Response,render_template,request,flash,redirect,session,g
import joblib
import pandas as pd
import numpy as np
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import MinMaxScaler,TransformerMixin
from flexible import FlexibleScaler


UPLOAD_FOLDER = '/tmp/'
ALLOWED_EXTENSIONS = {'csv'}
app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['ALLOWED_EXTENSIONS'] = ALLOWED_EXTENSIONS


@app.route("/",methods=["POST","GET"])
def home():

    if request.method == 'POST':

        //get data to process

        clf = joblib.load('ENS_fitted.joblib')

        prediction = clf.predict(features)
        pred_prob = clf.predict_proba(features)

        //do operations and return template

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

全部在本地运行。在Heroku上进行部署后,在joblib.load()上出现以下错误

Traceback (most recent call last):

2020-09-24T21:27:30.117559+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/app.py",line 2447,in wsgi_app

2020-09-24T21:27:30.117559+00:00 app[web.1]:     response = self.full_dispatch_request()

2020-09-24T21:27:30.117560+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/app.py",line 1952,in full_dispatch_request

2020-09-24T21:27:30.117560+00:00 app[web.1]:     rv = self.handle_user_exception(e)

2020-09-24T21:27:30.117561+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/app.py",line 1821,in handle_user_exception

2020-09-24T21:27:30.117561+00:00 app[web.1]:     reraise(exc_type,exc_value,tb)

2020-09-24T21:27:30.117561+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/_compat.py",line 39,in reraise

2020-09-24T21:27:30.117562+00:00 app[web.1]:     raise value

2020-09-24T21:27:30.117563+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/app.py",line 1950,in full_dispatch_request

2020-09-24T21:27:30.117563+00:00 app[web.1]:     rv = self.dispatch_request()

2020-09-24T21:27:30.117563+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/flask/app.py",line 1936,in dispatch_request

2020-09-24T21:27:30.117564+00:00 app[web.1]:     return self.view_functions[rule.endpoint](**req.view_args)

2020-09-24T21:27:30.117564+00:00 app[web.1]:   File "/app/flask_start.py",line 138,in home

2020-09-24T21:27:30.117564+00:00 app[web.1]:     clf = joblib.load('ENS_fitted.joblib')

2020-09-24T21:27:30.117565+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/joblib/numpy_pickle.py",line 585,in load

2020-09-24T21:27:30.117565+00:00 app[web.1]:     obj = _unpickle(fobj,filename,mmap_mode)

2020-09-24T21:27:30.117566+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/site-packages/joblib/numpy_pickle.py",line 504,in _unpickle

2020-09-24T21:27:30.117566+00:00 app[web.1]:     obj = unpickler.load()

2020-09-24T21:27:30.117567+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/pickle.py",line 1210,in load

2020-09-24T21:27:30.117570+00:00 app[web.1]:     dispatch[key[0]](self)

2020-09-24T21:27:30.117570+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/pickle.py",line 1526,in load_global

2020-09-24T21:27:30.117570+00:00 app[web.1]:     klass = self.find_class(module,name)

2020-09-24T21:27:30.117571+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.8/pickle.py",line 1581,in find_class

2020-09-24T21:27:30.117571+00:00 app[web.1]:     return getattr(sys.modules[module],name)

AttributeError: module '__main__' has no attribute 'FlexibleScaler'

我不知道为什么会这样。导入文件在那里,可以在本地工作。 我尝试将类FlexibleScaler直接复制到flask_start.py(也可以在本地运行),但是没有运气。

本地和Heroku之间唯一的变化是在Heroku上,我使用gunicorn来启动应用程序。

请帮助我们。

解决方法

我会尝试

clf = joblib.load('ENS_fitted.joblib')

放入try-except块中,以查看异常是否与您得到的相同

AttributeError: module '__main__' has no attribute 'FlexibleScaler'

例如:

try:

    clf = joblib.load('ENS_fitted.joblib')
    prediction = clf.predict(features)
    pred_prob = clf.predict_proba(features)

except Exception as e:

    print(f"Exception: {e}")

此外,我建议通过打印自己的通知来确保gunicorn以 name ==“ main ”的身份调用程序;

if __name__ == "__main__":
    print("__name__ is __main__")
    app.run(debug = True)

如果执行此操作后仍无法解决错误,我将考虑使用flask配置gunicorn。

,

似乎joblib.save()中产生ENS_fitted.joblib的{​​{1}}是直接从python运行的。在这种情况下,flask_start.py的{​​{1}}为flask_start。然后,当__name__泡菜时,它将FlexibleScaler实例另存为"__main__"

但是,当您在“大炮”下部署和运行时,joblib.save()的{​​{1}}为__main__.FlexibleScaler。这会使flask_start感到困惑,它希望找到一个__name__,并如上所示放弃了。

对此的一种解决方案是重新生成保存的模型,但这一次是通过以下方式调用"flask_start"

joblib.load()

然后再次__main__.FlexibleScaler,然后重新部署。

已更新

如果您完全无法重新生成模型,则可以尝试使用此技巧。在flask_start中导入后,添加

% FLASK_APP=flask_start flask run

您将能够joblib.save()建立模型,或者在另一个类中遇到类似的错误,在这种情况下,请重复此技巧。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?