如何解决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 举报,一经查实,本站将立刻删除。