使用pyenv和virtualenv在apache后面部署flask应用程序时找不到numpy,pandas模块
Posted
技术标签:
【中文标题】使用pyenv和virtualenv在apache后面部署flask应用程序时找不到numpy,pandas模块【英文标题】:numpy, pandas modules not found when deploying flask app behind apache with pyenv and virtualenv 【发布时间】:2017-12-07 04:09:49 【问题描述】:我为一个相当详细的应用程序构建了一个烧瓶前端,经过大量编码后,它在本地完美运行。所以现在我想让它对公众可见,所以已经读过它需要一个 apache 或 nginx 前端。我计算出我需要的实例大小并在 AWS 上将其打开,并运行了 these 两个 tutorials,这证明基本情况是有效的。 Apache 设置完成后,当我导航到 AWS 实例的 IP 时,会显示 Apache 欢迎页面。然后,当我暂时将“Hello World”代码替换为我的烧瓶应用程序并使用 IP 刷新浏览器时,hello world 出现了。此外,如果我用 here 替换 flasskapp.py 代码,它可以完美地跨 apache 提供输入到浏览器中的 IP 由 pip 找到的模块列表,包括 Numpy 和 Pandas,否则它会抱怨找不到!但是,可以通过在顶部添加 import numpy
轻松杀死此脚本,但它给了我以下错误消息:
ImportError: cannot import name 'multiarray'
和
Importing the multiarray numpy extension module failed. Most
likely you are trying to import a failed build of numpy.
If you're working with a numpy git repo, try `git clean -xdf`
(removes all files not under version control).
Otherwise reinstall numpy.
都在 apache 日志中。
当我放回我的应用程序而不是 hello world 时,就会出现问题。它只是拒绝导入 pandas,这是 Apache 日志的最后一部分:
Mon Jul 03 19:42:14.691081 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] Traceback (most recent call last):
[Mon Jul 03 19:42:14.691126 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] File "/var/www/html/flaskapp/flaskapp.wsgi", line 30, in <module>
[Mon Jul 03 19:42:14.691130 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] from similar_items_frontend import app as application
[Mon Jul 03 19:42:14.691137 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] File "/var/www/html/flaskapp/similar_items_frontend.py", line 4, in <module>
[Mon Jul 03 19:42:14.691140 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] from item_similar_to_doc import similar_to_doc
[Mon Jul 03 19:42:14.691145 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] File "/home/ubuntu/find-similar/frontend/../item_similar_to_doc.py", line 1, in <module>
[Mon Jul 03 19:42:14.691148 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] from PullVectors import p
[Mon Jul 03 19:42:14.691153 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] File "/home/ubuntu/find-similar/frontend/../RunSimilarity.py", line 5, in <module>
[Mon Jul 03 19:42:14.691156 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] import pandas as pd
[Mon Jul 03 19:42:14.691161 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] File "/home/ubuntu/.pyenv/versions/miniconda3-latest/envs/find_similarProject/lib/python3.6/site-packages/pandas/__init__.py", line 19, in <module>
[Mon Jul 03 19:42:14.691164 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] "Missing required dependencies 0".format(missing_dependencies))
[Mon Jul 03 19:42:14.691180 2017] [wsgi:error] [pid 12300:tid 140131159766784] [client 93.21.05.132:52560] ImportError: Missing required dependencies ['numpy']
我觉得我什么都试过了
这里是000-default.conf
:
WSGIPythonPath /home/ubuntu/.pyenv/versions/miniconda3-latest/envs/vtenv4YTproject/lib/python3.6/site-packages/
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
WSGIDaemonProcess flaskapp threads=5
WSGIScriptAlias / /var/www/html/flaskapp/flaskapp.wsgi
<Directory flaskapp>
WSGIScriptReloading On
WSGIProcessGroup %GLOBAL
WSGIApplicationGroup %GLOBAL
Order allow,deny
Allow from all
</Directory>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog $APACHE_LOG_DIR/error.log
CustomLog $APACHE_LOG_DIR/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
我应该提一下,当我通过 ssh 进入 AWS 实例时,我的烧瓶应用程序在其 virtualenv 中完美运行(直到烧瓶为页面提供服务),当然要让它工作有点修修补补,但它找到它的所有依赖项,而不是在 pandas 导入时崩溃。
为了尝试修复它,我查看了 here、here,添加了来自 here 的一些代码,查看了大量文档 here,我的 flaskapp.wsgi 文件如下所示:
import sys
import logging
import os.path
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
import config
import site
prev_sys_path = list(sys.path)
site.addsitedir('/home/ubuntu/.pyenv/versions/miniconda3-latest/envs/find_similarProject/lib/python3.6/site-packages')
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/var/www/html/flaskapp")
from similar_vids_frontend import app as application
application.secret_key = config.WSGI_KEY
我没有理由找到为什么 pandas / numpy 导入在 apache 上失败但在 virtualenv 中运行时工作正常。根据文档,我想知道是否与权限和组有关:
请注意,Apache 运行您的代码的用户需要能够访问 Python 虚拟环境。在某些 Linux 发行版上,其他用户无法访问用户帐户的主目录。与其更改主目录的权限,不如考虑将 WSGI 应用程序代码和任何 Python 虚拟环境放在主目录之外。
但是 Ubuntu 是 那些 发行版之一,然后将虚拟环境和项目安装到 /
文件夹中?
感谢任何提示或解决方案。
【问题讨论】:
this question 对您有帮助吗? 谢谢。我看到了,但不知道“守护程序模式”是什么或我是否正在使用它。我开始认为是我在使用github.com/pyenv/pyenv-virtualenv,但实际上并没有使用sudo apt install virtualenv
,尽管一切都在运行,除非 apache 尝试运行它
您正在使用WSGIDaemonProcess
,所以我认为您确实在使用答案所说的守护进程模式。您是否尝试过答案建议的解决方法?
给WSGIProcessGroup
的值应该与WSGIDaemonProcess
指令的名称相匹配。另一篇文章是关于 WSGIApplicationGroup
的,但不同。
Python 3.6 工作正常,但 mod_wsgi 必须已为其编译。您不能像我之前所说的那样尝试强制为 3.5 编译的 mod_wsgi 使用用 3.6 创建的虚拟环境。使用modwsgi.readthedocs.io/en/develop/user-guides/… 中的过程来验证您的 mod_wsgi 是如何构建的。
【参考方案1】:
这现在有效,主要归功于 Graham 的配方 here 和 this answer 关于将模块加载到 apache 中的方法。它有效的证明是 hello world 应用程序的以下变体:
from flask import Flask
import numpy
app = Flask(__name__)
@app.route('/')
def hello_from_np():
a = numpy.array([4,5,6])
return str(a)
if __name__ == '__main__':
app.run()
当您转到 IP 时,在浏览器中为您提供此信息:
...而不是 apache 日志中关于 numpy 的一堆错误。 这一切都是为 Python 3.6 设置的:
AH00489: Apache/2.4.7 (Ubuntu) mod_wsgi/4.5.15 Python/3.6 configured
想记录一些细节作为给自己的便条,以防万一有人遇到麻烦并试图重现这一点,也许可以让你免于找错树的日子。..
所以我从 Ubuntu Server 16.04 切换到 14.04.5 LTS,以防万一这是问题的一部分,也因为 pyenv 性能不佳,在安装我正在测试的许多旧 Python 版本的过程中崩溃。还选择省略 pyenv-virtualenv,因为没有为此实例计划多个项目,而且出错的事情更少。
从 Ubuntu 的全新安装中,除了安装 apache2、pyenv、libapache2-mod-wsgi,用 a2enmod 激活它之外,我特意在用 pip 安装要求之前运行了以下几行,其中包括 numpy,所以它没有抱怨:
sudo apt-get install gcc
sudo apt-get install g++
这也是需要的:
sudo apt-get install apache2-dev
然后在环境里面,在需求之后,
pip install mod_wsgi
mod_wsgi-express module-config
返回的第二行:
LoadModule wsgi_module "/home/ubuntu/.pyenv/versions/miniconda3-latest/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so"
WSGIPythonHome "/home/ubuntu/.pyenv/versions/miniconda3-latest"
然后在加载模块时,docs 鼓励您粘贴到文件 httpd.conf 中,至少在我的 apache 和 ubuntu 版本中不存在该文件。经过大量阅读,我避免创建一个,也避免将其粘贴到似乎是related 的 apache2.conf 中。相反,按照顶部链接到的 ubuntu 的说明,
编辑此文件:
sudo vi /etc/apache2/mods-available/wsgi.load
将此行粘贴到其中并保存:
LoadModule wsgi_module /path/to/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
然后运行它并在必要时重新启动 apache 服务器:
sudo a2enmod wsgi
000-default.conf 看起来像这样:
WSGIPythonHome "/home/ubuntu/.pyenv/versions/miniconda3-latest"
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
WSGIDaemonProcess helloapp threads=5 python-path=/var/www/html/frontend/
WSGIScriptAlias / /var/www/html/frontend/helloapp.wsgi
<Directory flaskapp>
WSGIProcessGroup helloapp
WSGIApplicationGroup %GLOBAL
Order allow,deny
Allow from all
</Directory>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog $APACHE_LOG_DIR/error.log
CustomLog $APACHE_LOG_DIR/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
【讨论】:
虽然出于原始问题的目的,这个 000-default.conf 有效,即 Numpy 导入,嗯,这比小说更奇怪,但 scipy 不导入!此外,它甚至不会像import numpy
那样抛出错误消息!要解决此问题,请参阅 here WSGIApplicationGroup %GLOBAL
行需要从它所在的位置移动到 WSGIScriptAlias
行下方
<Directory flaskapp>
应该是 <Directory /var/www/html/frontend>
。因为它是你甚至不会使用守护程序模式。由于访问被禁止,Apache 没有使请求失败,这表明您在 Apache 其他地方的权限很松懈,让 Apache 从文件系统的任何位置提供内容。建议你在VirtualHost
之外加上WSGIRestrictEmbedded On
,如果误用嵌入模式会导致失败。
您的命令(位于底部的 VirtualHost 下方)在自周六以来一直运行良好之后确实破坏了它:Embedded mode of mod_wsgi disabled by runtime configuration: /var/www/html/frontend/flaskapp.wsgi
我现在需要它在线,已经分享了链接,所以希望没有人找到同时破解它的方法,再次删除WSGIRestrictEmbedded On
。可能授予对前端文件夹中文件的 execute 权限就足够了,不需要将整个 Python 存储库添加到 www-data 组。将找出安全设置并在一天中的安静时间恢复。
应该会导致任何安全问题,如果 Apache 服务器使用更适合静态文件和 php 应用程序的典型配置,则使用嵌入式模式会有性能和可恢复性问题。阅读blog.dscpl.com.au/2012/10/…
感谢您提供的链接对于具有大内存占用的动态 Web 应用程序来说不一定能很好地工作,当持久保存在内存中时性能会更好。很好,它不会被黑客入侵,它使用大量内存并且到目前为止已经崩溃过一次。将在一周左右尝试将其正确转换为守护程序模式。以上是关于使用pyenv和virtualenv在apache后面部署flask应用程序时找不到numpy,pandas模块的主要内容,如果未能解决你的问题,请参考以下文章
pyenv、virtualenv、anaconda 有啥区别?
Python 杂记之 如何使用pyenv进行版本管理与如何使用virtualenv创建虚拟运行环境
如何配置全局主管以使用 pyenv 和 virtualenv