numpy,在使用 pyenv 和 virtualenv 在 apache 后面部署 flask 应用程序时找不到 pandas 模块

numpy, pandas modules not found when deploying flask app behind apache with pyenv and virtualenv

我为一个相当详细的应用程序构建了一个 Flask 前端,经过大量编码后,它 运行 在本地非常完美。所以现在我想让它对 public 可见,所以我读到它需要一个 apache 或 nginx 前端。我计算出我需要的实例的大小并在 AWS 上打开它,并且 运行 到 these two tutorials which prove that the base case is working. Once the Apache setup is done, the Apache welcome page shows when I navigate to the IP of the AWS instance. Then when I temporarily substitute the "Hello World" code for my flask app and refresh the browser with the IP, the hello world appears rendered. Also, if I substitute the flasskapp.py code from 它完美地跨 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 实例时,我的 Flask 应用程序 运行 在它的 virtualenv 中完美地(到了 Flask 为页面服务的地步),当然是有点修补让它工作,但它找到了它的所有依赖项,而不是在 pandas 导入时崩溃。

为了尝试修复它,我查看了 , here, added some code from here, went through the extensive docs 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 中仅 运行 时工作正常。根据文档,我想知道是否与权限和组有关:

Do be aware that the user that Apache runs your code as will need to be able to access the Python virtual environment. On some Linux distributions, the home directory of a user account is not accessible to other users. Rather than change the permissions on your home directory, it might be better to consider locating your WSGI application code and any Python virtual environment outside of your home directory.

但是 Ubuntu 是 那些 发行版之一,然后呢,将虚拟环境和项目安装到 / 文件夹中?

感谢任何提示或解决方案。

这现在可以工作了,这主要归功于 Graham 关于将 mod 规则加载到 Apache 中的秘诀 and also this answer。它有效的证明是 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 服务器 16.04 切换到 14.04.5 LTS 以防这是问题的一部分,但也因为 pyenv 性能不佳,在安装许多旧版本的过程中崩溃Python 个我正在测试的版本。还选择省略 pyenv-virtualenv,因为没有为此实例计划多个项目,而且出错的事情少了一件。

从Ubuntu的全新安装开始,除了安装apache2、pyenv、libapache2-mod-wsgi,用a2en激活mod,我特意运行 在使用 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"

然后加载 module,docs encourages you to paste into a file httpd.conf which at least in my version of apache and ubuntu does not exist. After a lot of reading, I avoided creating one and also avoided pasting it into apache2.conf which seems to be related。相反,按照顶部链接的 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>