Docker ModuleNotFoundError, хотя этот модуль больше не включен в код - PullRequest
0 голосов
/ 21 апреля 2020

Я написал Flask API, который я хочу запустить в docker контейнере. Тем не менее, Error: While importing "api", an ImportError was raised: продолжает появляться, даже если модуль, который не найден, больше не содержится в коде.

После возникновения ошибки я остановил, удалил и перезапустил контейнер Docker, чтобы запустить Flask Api:

docker stop privacy_api
docker rm privacy_api
docker build -t privacy_api_image .
docker run -dit --name=privacy_api -e FLASK_APP=api.py -p 5000:5000 -v main_api:/app --network privacy-network privacy_api_image
5963fb7fa194d6710ae5e713d2060bd0be5338b04636bf306b78bda4bb596524

docker logs -f privacy_api

Тем не менее, это вывод, который я получаю:

* Serving Flask app "api.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
Usage: flask run [OPTIONS]

    Error: While importing "api", an ImportError was raised:

    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/site-packages/flask/cli.py", line 240, in locate_app
        __import__(module_name)
      File "/app/api.py", line 2, in <module>
        from flask_cors import CORS, cross_origin
    ModuleNotFoundError: No module named 'flask_cors'

Это мой код api.py:

from flask import Flask, request, Response, jsonify
import MySQLdb
import json
import logging
import formscripts as priv
import databreach
from datetime import datetime
import pytz #needs to be added to Docker!

app = Flask(__name__)

def get_db_connection():
    cursor=None
    if not cursor:
        connection = MySQLdb.connect("privacy-mysql", "root", "DockerPasswort!", "privacydatabase")
        cursor = connection.cursor()
    return cursor, connection

@app.route('/data_remove', methods=["POST"])
def data_takedown():
    print("in takedown")
    cursor, connection = get_db_connection()
    data = request.get_json()
    email_login=False
    email_pw=""
    title = data["title"]
    firstname = data["firstname"]
    lastname = data["lastname"]
    suffix = data["suffix"]
    email = data["email"]
    phone_num = data["phone_num"]
    street = data["street"]
    apt = data["apt"]
    city = data["city"]
    state = data["state"]
    country = data["country"]
    zip_code = data["zip_code"]
    cc_last4 = data["cc_last4"]
    data_del_msg = data["data_del_msg"]
    deviceAdID = data["deviceAdID"]
    privacyReg = data["privacyReg"]
    if "email_pw" in data:
        email_login=True
        email_pw=data["email_pw"]
    #############################################
    ####### privacy form script functions #######
    #############################################
    if email_login==True:
        email_result = requests.post('http://localhost:5001/email', json={
    "from_email": email,
    "password": email_pw,
    "to_email": "consumeradvo@acxiom.com",
    "subject": "Acxiom Opt out request for: "+firstname+" "+lastname+" ("+email+")",
    "message": "Dear Acxiom Team, I would like you to remove my information. This is my name: "+firstname+" "+lastname+" "+suffix+". This is my phone_number: "+phone_num+", my email: "+email+ ". This is my address: Street: "+street+", Apartment: "+apt+", City: "+city+", State: "+state+", Zip: "+zip_code
    })
        #Feel free to test whether it works for you with gmail (it should if you change the commenting for the server in send_email.py) but somehow it doesn't for me
        """
        r = requests.post('http://localhost:5000/email', json={
            "from_email": "alexander.farr@gmail.com",
            "password": "Password",
            "to_email": "alexander.farr@hotmail.de",
            "subject": "subject test",
            "message": "body test"
        })
        """

    adColony = priv.adColony_DoNotSSP(email, firstname, lastname, privacyReg,
                                      deviceAdID)
    petco = priv.petco_delete(firstname, lastname, email, phone_num)
    linkedIn = priv.linkedIn_DataDelete(firstname, lastname, email,
                                        data_del_msg)
    chipotle = priv.chipotle_delete(firstname, lastname, email, phone_num,
                                    cc_last4)
    pipl = priv.pipl_delete(firstname, lastname, email, phone_num,
                            data_del_msg)
    asl = priv.asl_DD_formfill(firstname, lastname, street, city, state,
                               zip_code, phone_num, email)
    bestBuy = priv.bestBuy_DD_formfill(firstname, lastname, country, street,
                                       city, zip_code, phone_num, email)
    booking = priv.booking_DD_formfill(email)
    analyticsIQ=priv.analyticsIQ_DD_formfill(firstname, lastname, country, address, city, state, zipcode, email)
    asl=priv.asl_DD_formfill(firstname, lastname, address, city, state, zipcode, phone, email)

    ############
    #####TODO test whether next three functions are working and otherwise remove (also from database)#####
    ##########
    atlantic=priv.atlantic_DD_formfill(california_resident, email, zipcode)
    instantCheckmate=priv.instantCheckmate_DD_formfill(firstname, lastname, city)
    intelius=priv.intelius_DD_formfill(firstname, lastname, cityState)
    ####### Check for data breach  #######
    databreach=request_answer(email)
    ####### Insert into database   #######
    tz_LA = pytz.timezone('America/Los_Angeles')
    datetime_LA = datetime.now(tz_LA)
    timstamp=datetime_LA.strftime("%H:%M:%S")
    sql='INSERT INTO privacydb (timstamp, adColony, asl, analyticsiq, bestbuy, booking, chipotle, instantcheckmate, intelius, linkedin, petco, pipl, atlantic, databreach) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
    cursor.execute(sql, [timstamp, adColony, asl, analyticsIQ, bestBuy, booking, chipotle, instantCheckmate, intelius, linkedIn, petco, pipl, atlantic, databreach])
    connection.commit()
    cursor.close()
    connection.close()

    #TODO OUTPUT sending email
    return json.dumps({
        "adColony": adColony,
        "asl": asl,
        "analyticsIQ": analyticsIQ,
        "best buy": bestBuy,
        "booking.com": booking,
        "chipotle": chipotle,
        "instantCheckmate": instantCheckmate,
        "intelius": intelius,
        "linkedIn": linkedIn,
        "petco": petco,
        "pipl": pipl,
        "atlantic": atlantic,
        "databreach": databreach
    }), 200

Это Dockerfile:

FROM python:3
COPY . /app
WORKDIR /app
RUN pip install -r requirements-main-api.txt
EXPOSE 5000
ENTRYPOINT ["flask"]
CMD ["run", "--host=0.0.0.0"]

Это requirements-main-api.txt file:

flask==1.1.1
mysqlclient==1.4.6
selenium
requests
pytz

Я не понимаю ошибку, поскольку Cors больше не находится в файле api.py.

У вас есть идеи? Спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

Удалите параметр -v main_api:/app.

Для этого он берет содержимое именованного тома main_api и монтирует его поверх /app. Даже если ваш Dockerfile обновляет код в образе, этот параметр времени выполнения скрывает это изменение и использует вместо этого существующее содержимое тома.

Это, очевидно, работало в прошлом, потому что при первом (только) запуске Контейнер, содержимое изображения копируется в новый пустой том. Если в томе уже есть содержимое, Docker не будет перезаписывать потенциально важные пользовательские данные, поэтому, если вы попытаетесь поместить код своего приложения в именованный том, вы будете использовать фиксированную старую версию своего кода.

0 голосов
/ 21 апреля 2020

Вам нужно добавить Flask-Cors==1.10.3 в ваш файл требований-main-api.txt

Если вы уже удалили все вызовы зависимостей для этой библиотеки, то обязательно сохраните файл и снова запустите файл dockerfile с помощью --no-cache flag

Вы также можете удалить предыдущее изображение с помощью docker rmi <ImageNameOrID>, и если вы хотите очистить систему docker Daemon: docker system prune -a

...