当前位置: 首页 > 知识库问答 >
问题:

使用mod_wsgi在Apache上部署Flask

李宁
2023-03-14

我正在尝试部署我构建的用于部署在Apache服务器上的Flask Web应用程序。我在Raspberry Pi 3上使用Raspbian(Jessie)OS。该应用程序在flask内置的开发Web服务器上运行完美,但我无法在Apache服务器上部署它。

这就是我所做的:

sudo apt-get update
sudo apt-get -y install python3 ipython3 python3-flask
sudo apt-get -y install apache2
sudo apt-get -y install libapache2-mod-wsgi-py3

conf文件为:etc/apach2/sites available/arduinoweb。形态:

<VirtualHost *>
 ServerName 10.0.0.20

 WSGIDaemonProcess arduinoweb user=pi group=pi threads=5
 WSGIScriptAlias / /var/www/ArduinoWeb/arduinoweb.wsgi

<Directory /var/www/ArduinoWeb/ArduinoWeb>
 WSGIProcessGroup arduinoweb
 WSGIApplicationGroup %{GLOBAL}
 WSGIScriptReloading On
 Require all granted
</Directory>

Alias /static /var/www/ArduinoWeb/ArduinoWeb/static
<Directory /var/www/ArduinoWeb/ArduinoWeb/static/>
Require all granted
</Directory>

Alias /temp /var/www/ArduinoWeb/ArduinoWeb/temp
<Directory /var/www/ArduinoWeb/ArduinoWeb/temp/>
Require all granted
</Directory>

Alias /templates /var/www/ArduinoWeb/ArduinoWeb/templates
<Directory /var/www/ArduinoWeb/ArduinoWeb/templates/>
Require all granted
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined


</VirtualHost>
~

/var/www/Arduinoweb/arduinoweb.wsgi中的WSGI脚本文件:

import sys

if sys.version_info[0]<3:       # require python3
    raise Exception("Python3 required! Current (wrong) version: '%s'" % sys.version_info)

sys.path.insert(0, '/var/www/Arduinoweb/Arduinoweb')

from app import app as application

Apache的错误日志

[Wed Sep 21 21:46:22.669633 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Target WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi' cannot be loaded as Python module.
[Wed Sep 21 21:46:22.669971 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Exception occurred processing WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi'.
[Wed Sep 21 21:46:22.670196 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] Traceback (most recent call last):
[Wed Sep 21 21:46:22.671185 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819]   File "/var/www/ArduinoWeb/arduinoweb.wsgi", line 8, in <module>
[Wed Sep 21 21:46:22.671238 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819]     from app import app as application
[Wed Sep 21 21:46:22.671406 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] ImportError: No module named 'app'

我不明白为什么它找不到应用程序。

这是python文件。py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask import request, redirect, url_for, render_template, jsonify
from socket import *
from time import time
from threading import Timer
from datetime import datetime
import fileinput

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:Qazwsx@localhost/arduinoweb'
app.debug = True
db = SQLAlchemy(app)

class User(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email
    def __repr__(self):
        return '<user %r>' % self.username


class Temp(db.Model):
        __tablename__ = "Temp"
        id = db.Column("id", db.Integer, primary_key=True)
        Temp = db.Column("Temp", db.Integer)
        Date = db.Column("Date", db.Date)
        Time = db.Column("Time", db.Time)
        DateTime = db.Column("DateTime", db.String)

        def __init__(self, Temp, Date=None, Time=None, DateTime=None):
                self.Temp = Temp
                if Date is None:
                        Date = str(datetime.now()).split('.')[0]
                self.Date = Date
                if Time is None:
                        Time = str(datetime.now()).split('.')[0]
                self.Time = Time
                if DateTime is None:
                        DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
                self.DateTime = DateTime

class EC(db.Model):
        __tablename__ = "EC"
        id = db.Column("id", db.Integer, primary_key=True)
        EC = db.Column("EC", db.Float)
        Date = db.Column("Date", db.Date)
        Time = db.Column("Time", db.Time)
        DateTime = db.Column("DateTime", db.String)

        def __init__(self, EC, Date=None, Time=None, DateTime=None):
                self.EC = EC
                if Date is None:
                        Date = str(datetime.now()).split('.')[0]
                self.Date = Date
                if Time is None:
                        Time = str(datetime.now()).split('.')[0]
                self.Time = Time
                if DateTime is None:
                        DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
                self.DateTime = DateTime

class PH(db.Model):
        __tablename__ = "PH"
        id = db.Column("id", db.Integer, primary_key=True)
        PH = db.Column("PH", db.Float)
        Date = db.Column("Date", db.Date)
        Time = db.Column("Time", db.Time)
        DateTime = db.Column("DateTime", db.String)

        def __init__(self, PH, Date=None, Time=None, DateTime=None):
                self.PH = PH
                if Date is None:
                        Date = str(datetime.now()).split('.')[0]
                self.Date = Date
                if Time is None:
                        Time = str(datetime.now()).split('.')[0]
                self.Time = Time
                if DateTime is None:
                        DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
                self.DateTime = DateTime

class Humidity(db.Model):
        __tablename__ = "Humidity"
        id = db.Column("id", db.Integer, primary_key=True)
        Humidity = db.Column("Humidity", db.Integer)
        Date = db.Column("Date", db.Date)
        Time = db.Column("Time", db.Time)
        DateTime = db.Column("DateTime", db.String)

        def __init__(self, Humidity, Date=None, Time=None, DateTime=None):
                self.Humidity = Humidity
                if Date is None:
                        Date = str(datetime.now()).split('.')[0]
                self.Date = Date
                if Time is None:
                        Time = str(datetime.now()).split('.')[0]
                self.Time = Time
                if DateTime is None:
                        DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
                self.DateTime = DateTime

class HumidityRoots(db.Model):
        __tablename__ = "HumidityRoots"
        id = db.Column("id", db.Integer, primary_key=True)
        HumidityRoots = db.Column("HumidityRoots", db.Integer)
        Date = db.Column("Date", db.Date)
        Time = db.Column("Time", db.Time)
        DateTime = db.Column("DateTime", db.String)

        def __init__(self, HumidityRoots, Date=None, Time=None, DateTime=None):
                self.HumidityRoots = HumidityRoots
                if Date is None:
                        Date = str(datetime.now()).split('.')[0]
                self.Date = Date
                if Time is None:
                        Time = str(datetime.now()).split('.')[0]
                self.Time = Time
                if DateTime is None:
                        DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
                self.DateTime = DateTime


@app.route('/Sensors')
def sensors_function():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("GETSENSORS".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/OutputsState')
def outputs_state_function():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("GETOUTPUTSSTATE".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/WebModeState')
def web_mode_state_function():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("GETWEBMODE".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/PLCState')
def plcstatefunction():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("GETPLCSTATE".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/IrrigateOnOff')
def irrigate_on_off_function():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("IRRIGATEOnOff".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/SprinklersOnOff')
def sprinklers_on_off_function():
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto("SprinklersOnOff".encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return rec_data

@app.route('/SetDateTime' , methods=['POST'])
def set_date_time_function():
        completeAnswer =  "%s:%s:%s:%s:%s:%s:%s:%s" % ("SETDATETIME", request.form.get('dOw'), request.form.get('SetDate'), request.form.get('SetMonth'), request.form.get('SetYear'), request.form.get('SetHour'), request.form.get('SetMinute'), request.form.get('SetSeconds'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetIrrigation' , methods=['POST'])
def set_irrigation_function():
        completeAnswer =  "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % ("SETIRRIGATION",request.form.get('SetIrrigationMode'), request.form.get('SetHumidityRangeMin'), request.form.get('SetHumidityRangeMax'), request.form.get('SetHour1'), request.form.get('SetHour1OnTime'), request.form.get('SetHour1OffTime'), request.form.get('SetHour2'), request.form.get('SetHour2OnTime'), request.form.get('SetHour2OffTime'), request.form.get('SetHour3'), request.form.get('SetHour3OnTime'), request.form.get('SetHour3OffTime'), request.form.get('SetHour4'), request.form.get('SetHour4OnTime'), request.form.get('SetHour4OffTime'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetEC' , methods=['POST'])
def set_EC_function():
        completeAnswer =  "%s:%s:%s:%s:%s" % ("SETEC", request.form.get('SetECRangeMin'), request.form.get('SetECRangeMax'), request.form.get('SetDoseEC'), request.form.get('SetECDelay'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetPH' , methods=['POST'])
def set_PH_function():
        completeAnswer =  "%s:%s:%s:%s:%s:%s" % ("SETPH", request.form.get('SetPHRangeMin'), request.form.get('SetPHRangeMax'), request.form.get('SetDosePHUp'), request.form.get('SetDosePHDown'), request.form.get('SetPHDelay'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetWaterTemp' , methods=['POST'])
def set_water_temp_function():
        completeAnswer =  "%s:%s:%s" % ("SETWATERTEMP", request.form.get('SetWaterTempRangeMin'), request.form.get('SetWaterTempRangeMax'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetSprinklers' , methods=['POST'])
def set_sprinklers_function():
        completeAnswer =  "%s:%s:%s:%s:%s" % ("SETSPRINKLERS", request.form.get('SetSprinklersBeginEndHoursBegin'), request.form.get('SetSprinklersBeginEndHoursEnd'), request.form.get('SetSprinklersOnTime'), request.form.get('SetSprinklersOffTime'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/SetAlerts' , methods=['POST'])
def set_alerts_function():
        completeAnswer =  "%s:%s:%s:%s:%s:%s" % ("SETALERTS", request.form.get('SetIrrigationThresholdAlert'), request.form.get('ECAlertOffset'), request.form.get('PHAlertOffset'), request.form.get('ResetCounterState'), request.form.get('AlertsState'))
        address= ( '192.168.0.196', 5000) #define server IP and port
        client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
        client_socket.settimeout(1) #Only wait 1 second for a response
        client_socket.sendto(completeAnswer.encode(), address) #Send the data request
        rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
        return "ok"

@app.route('/')
def index():
        return render_template('index.html')

@app.route('/Charts')
def charts():
        return render_template('charts.html')

@app.route('/livechart')
def live_chart():
        return render_template('livechart.html')

@app.route('/TempQuery' , methods=['POST'])
def temp_query():
        answerDate = request.form.get('date')
        answerSensor = request.form.get('sensor')
        datafile = 'temp/TempByDateDbFile.txt'
        if answerSensor == 'Temp':
                DbTemp = Temp.query.filter_by(Date = answerDate).all()
                ## create the file from db
                file = open(datafile, 'w')
                for item in DbTemp:
                        file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Temp) + '},' + '\n')
                file.close()
        elif  answerSensor == 'EC':
                DbTemp = EC.query.filter_by(Date = answerDate).all()
                ## create the file from db
                file = open(datafile, 'w')
                for item in DbTemp:
                        file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.EC) + '},' + '\n')
                file.close()
        elif  answerSensor == 'PH':
                DbTemp = PH.query.filter_by(Date = answerDate).all()
                ## create the file from db
                file = open(datafile, 'w')
                for item in DbTemp:
                        file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.PH) + '},' + '\n')
                file.close()
        elif  answerSensor == 'Humidity':
                DbTemp = Humidity.query.filter_by(Date = answerDate).all()
                ## create the file from db
                file = open(datafile, 'w')
                for item in DbTemp:
                        file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Humidity) + '},' + '\n')
                file.close()
        elif  answerSensor == 'HumidityRoots':
                DbTemp = HumidityRoots.query.filter_by(Date = answerDate).all()
                ## create the file from db
                file = open(datafile, 'w')
                for item in DbTemp:
                        file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.HumidityRoots) + '},' + '\n')
                file.close()
        ##replace "-" in ","
        f = open(datafile,'r')
        filedata = f.read()
        f.close()
        newdata = filedata.replace("-",", ")
        f = open(datafile,'w')
        f.write(newdata)
        f.close()
        return 'OK'

@app.route('/RenderTempChart' , methods=['POST' , 'GET'])
def render_temp_chart():
        datafile = 'temp/TempByDateDbFile.txt'
        with open(datafile, 'r') as myfile:
                file = myfile.read()
        return render_template('DbTemp.html', file = file)

@app.route('/Control' , methods=['POST' , 'GET'])
def control():
        return render_template('control.html')
"""
def update_data(interval):  # store in DB all sensors real time data
        Timer(interval, update_data, [interval]).start()
        SensorsAnswer = sensors_function().split()
        addTemp = Temp(int(SensorsAnswer[2]))
        addEC = EC(float(SensorsAnswer[0]))
        addPH = PH(float(SensorsAnswer[1]))
        addHumidity = Humidity(int(SensorsAnswer[3]))
        addHumidityRoots = HumidityRoots(int(SensorsAnswer[5]))
        db.session.add(addTemp)
        db.session.add(addEC)
        db.session.add(addPH)
        db.session.add(addHumidity)
        db.session.add(addHumidityRoots)
        db.session.commit()

update_data(300) # Store data in DB every x seconds
"""
if __name__ == "__main__":
        app.run()

即使是这样一个简单的代码,它也不起作用(相同的错误):

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello world!"

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

我正在使用python 3.4.2。我没有在虚拟环境中使用它。

文件夹结构:

<代码>应用程序。py位于www/Arduinoweb/Arduinoweb/app。py。wsgi位于www/Arduinoweb/Arduinoweb。wsgi

我确实启用了VirtualHostarduinoweb.conf并重新启动apach2服务。

共有2个答案

漆雕奇逸
2023-03-14

谢谢你的帮助。。最终,这似乎只是wsgi脚本路径中的一个键入错误:“/var/www/ArduinoWeb/ArduinoWeb”而不是“/var/www/ArduinoWeb/ArduinoWeb”。

现在它似乎工作得很好。谢谢

蓝夕
2023-03-14

首先,这:

<Directory /var/www/ArduinoWeb/ArduinoWeb>
 WSGIProcessGroup arduinoweb
 WSGIApplicationGroup %{GLOBAL}
 WSGIScriptReloading On
 Require all granted
</Directory>

应该是:

<Directory /var/www/ArduinoWeb>
 WSGIProcessGroup arduinoweb
 WSGIApplicationGroup %{GLOBAL}
 Require all granted
</Directory>

从技术上讲,这一错误将导致两个问题。

首先,Apache甚至不应该允许您使用WSGI脚本,因为它没有权限。看起来,Apache配置中的其他地方正在为您的文件系统提供广泛的访问权限,而实际上不应该这样做。

我还放弃了重新加载选项,因为默认设置为on,并且不需要。

第二个是WSGI脚本不会在守护进程组的上下文中运行。这意味着代码将改为以嵌入式模式加载并以Apache用户身份运行。如果文件的权限只有pi用户可以读取它们,那么它将无法访问app模块。

将服务器名作为IP地址通常也是错误的。如果它可以工作,那么它只能这样做,因为这是Apache配置中的第一个虚拟主机,因此Apache在无法正确进行基于名称的虚拟主机匹配时默认使用它。

无论如何,看看这是否有帮助,否则提供运行的输出:

ls -las /var/www/ArduinoWeb /var/www/ArduinoWeb/ArduinoWeb

因此可以检查目录/文件的所有权/权限。

 类似资料:
  • 问题内容: 我想在同一主机中部署两个不同的django应用程序:第一个将对应于URL / site1,第二个将对应于URL / site2。这是我的配置: 这也是这两个应用程序的wsgi.py文件 现在,这是我的问题。当我转到服务器时,假设http://app1.sites.gr/site1有时加载了site1,而有时加载了site2!访问http://app1.sites.gr/site2时也是

  • 下面的步骤在Apache-2.2.3 (Red Hat Enterprise Linux 5.2, x86_64),mod_wsgi-2.0中测试通过。(译者注:本人在Windows2003 + Apache-2.2.15 + mod_wsgi-3.0也测试通过) 注意: 您可以使用您自己的项目名称替换’appname’。 您可以使用您自己的文件名称替换’code.py’。 /var/www/we

  • 我想在同一个主机上部署两个不同的django应用程序:第一个对应于url/site1,第二个对应于url/site2。这是我的配置: 这是两个应用程序的wsgi.py文件 现在,我的问题来了。当我转到服务器时,假设http://app1.sites.gr/site1它有时加载site1,有时加载site2!!!!我访问时也是如此http://app1.sites.gr/site2 ... 有时我会

  • 本文向大家介绍CentOS7部署Flask(Apache、mod_wsgi、Python36、venv),包括了CentOS7部署Flask(Apache、mod_wsgi、Python36、venv)的使用技巧和注意事项,需要的朋友参考一下 一、安装Apache 防火墙开放80端口 开启Apache,外网已经可以通过ip访问Apache的默认页面了 二、安装Python36、pip3、virtu

  • 我想在Apache服务器上部署我的Flask应用程序。我在服务器上有一个帐户,并被告知“服务器可用于运行用Python编写的脚本和Web应用程序(使用django和mod_wsgi)”。 我在Windows上,要传输文件,我必须使用FTP客户端,所以我使用WinSCP。 安装mod_wsgi并不像我预期的那样简单,我无法在线获得任何清晰的文档。 因为服务器已经可以使用mod_wsgi运行Pytho

  • 问题内容: 有人可以解释守护程序模式下的apache mod_wsgi和线程模式下的django fastcgi之间的区别。我认为它们都使用线程进行并发。 假设我将nginx用作Apache mod_wsgi的前端。 更新: 我正在比较在fastemon中内置的django(./manage.py method = threaded maxchildren = 15)和mod_wsgi在“守护程序