У меня есть приложение Flask
, работающее в среде docker
с двумя SQAlchemy
базами данных:
Postgres
(на основе сети) Sqlite
( на основе файла)
Это моя docker-compose
конфигурация, работающая на Linux
VM в MacOS
:
services:
web:
build:
context: ./services/web
dockerfile: Dockerfile-dev
volumes:
- './services/web:/usr/src/app'
ports:
- 5001:5000
environment:
- FLASK_ENV=development
- APP_SETTINGS=project.config.DevelopmentConfig
- DATABASE_URL=postgres://postgres:postgres@web-db:5432/web_dev
- DATABASE_TEST_URL=postgres://postgres:postgres@web-db:5432/web_test
- DATABASE_INDEX_URL=sqlite:////usr/src/app/project/db/index/searchindex.db
- SECRET_KEY=my_precious
depends_on:
- web-db
- redis
worker-scraping:
image: dev3_web
restart: always
volumes:
- ./services/web:/usr/src/app
- ./services/web/celery_logs:/usr/src/app/celery_logs
command: celery worker -A celery_worker.celery --loglevel=DEBUG --logfile=celery_logs/worker_scraping.log -Q scraping
environment:
- CELERY_BROKER=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
- FLASK_ENV=development
- APP_SETTINGS=project.config.DevelopmentConfig
- DATABASE_URL=postgres://postgres:postgres@web-db:5432/web_dev
- DATABASE_TEST_URL=postgres://postgres:postgres@web-db:5432/web_test
- DATABASE_INDEX_URL=sqlite:////usr/src/app/project/db/index/searchindex.db
- SECRET_KEY=my_precious
depends_on:
- web
- redis
- web-db
links:
- redis:redis
- web-db:web-db
config.py
class DevelopmentConfig(BaseConfig):
"""Development configuration"""
SECRET_KEY = os.environ.get('SECRET_KEY')
#sqlalchemy
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
SQLALCHEMY_DATABASE_INDEX_URI = os.environ.get('DATABASE_INDEX_URL')
SQLALCHEMY_BINDS = {
'db1': SQLALCHEMY_DATABASE_URI,
'db2': SQLALCHEMY_DATABASE_INDEX_URI
}
CELERY_BROKER_URL = os.environ.get('CELERY_BROKER')
CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND')
CELERY_IMPORTS = ('project.api.routes.background',)
Мое sqlite
соединение должно быть установлено с помощью celery
фонового процесса, например так:
@celery.task(
queue='scraping',
default_retry_delay=30,
max_retries=3,
soft_time_limit=100000)
def scrape_allblogs():
# celery worker -A celery_worker.celery --loglevel=INFO -Q scraping
blog_crawler = crawler(current_app.config.get('SQLALCHEMY_DATABASE_INDEX_URI'))
blog_crawler.create_index_tables() #DONE once
for pagelist in all_pagelists:
blog_crawler.crawl([pagelist])
return {'Status': 'Blogs indexing updated!'}
и вот как метод создания и заполнения базы данных Выше было определено:
searchengine.py
class crawler:
# Initialize the crawler with the name of database
def __init__(self, dbname):
self.con = sqlite3.connect(
dbname,
timeout=10)
def __del__(self):
self.con.close()
def dbcommit(self):
self.con.commit()
и, наконец, вот как я инициализирую приложение:
__init __. py
import os
# third party libs
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from celery import Celery
from flask_migrate import Migrate
# background processes instance
celery = Celery(__name__, broker='redis://redis:6379/0')
# extensions
migrate = Migrate()
def create_app(script_info=None):
from .api.models.base import db
from .api import routes, models
# instantiate the app
app = Flask(__name__)
# set config
app_settings = os.getenv('APP_SETTINGS')
app.config.from_object(app_settings)
# set up extensions
migrate.init_app(app, db)
routes.init_app(app)
models.init_app(app)
celery.conf.update(app.config)
# shell context for flask cli
@app.shell_context_processor
def ctx():
return {'app': app, 'db': db}
return app
Несмотря на объявление d1
и d2
в config.py
, я только привязываю модели к моей базе данных Postgres
(d1
), поэтому далеко, потому что мне нужен только доступ к d2
на данном этапе разработки:
class User(db.Model):
__tablename__ = 'users'
__bind_key__ = 'db1'
Когда я поднимаю свои контейнеры, пустой файл searchindex.db
создается по правильному пути, но я ' m получает следующую ошибку:
[2020-02-17 18:55:47,033: DEBUG/MainProcess] pidbox received method enable_events() [reply_to:None ticket:None]
[2020-02-17 18:55:47,062: ERROR/ForkPoolWorker-1] Task project.api.routes.background.scrape_allblogs[6b02fe39-a51c-4a5d-8ee8-13af3a15180e] raised unexpected: OperationalError('unable to open database file')
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/celery/app/trace.py", line 385, in trace_task
R = retval = fun(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/celery/app/trace.py", line 648, in __protected_call__
return self.run(*args, **kwargs)
File "/usr/src/app/project/api/routes/background.py", line 905, in scrape_allblogs
blog_crawler = crawler(current_app.config.get('SQLALCHEMY_DATABASE_INDEX_URI'))
File "/usr/src/app/project/api/classifiers/nlp/searchengine.py", line 201, in __init__
timeout=10)
sqlite3.OperationalError: unable to open database file
* 10 60 * Чего мне не хватает? Как разблокировать базу данных sqlite?