Как правильно управлять путями при использовании RQ работников, очередей и заданий - PullRequest
2 голосов
/ 08 марта 2019

Мой первый вопрос / пост ... пожалуйста, будьте добры ....

Я работаю над личным проектом, в котором один модуль работает в цикле сбора данных.Когда данные поступают, они вручную вставляют данные в базу данных в функцию в очереди, где прослушивающий сотрудник rq забирает их и обрабатывает функцию.База данных управляется с использованием SQLAlchemy, что означает, что она должна генерировать механизм, сеанс и определять таблицу базы данных.

Структура файлов кода:

--/home/..../collect-view/  (this is the project folder)
    -- DataCollection
        -- main_client.py  (main loop waiting for user data)
        -- collect_data.py (contains the database insertion function)
        -- base.py         (the base file for SQLAlchemy database definition)
        -- tables.py       (the file which sets up the table name and definition)
    -- app.db                  (the database file)

Примечание: файл базы данныхв каталоге более высокого уровня, поскольку к нему также обращается другое приложение (приложение Flask), которое также находится на этом уровне

Чтобы реализовать этот код, «collect_data» должен импортировать «base» и «tables» и «tables»должен импортировать "базу".Это оказалось проблемой, поскольку, как только работник запускает функцию collect_data (называемую «передача»), он больше не может найти файлы для импорта, и работник выдает исключение, говоря, что не может импортировать базу.».Я искал ответы в Интернете и в конце концов нашел ответ на Github от nvie, в котором упоминалось, как направить работника по правильному пути, используя параметр --path.Я запустил его, реализовав:

$ rq worker rq_worker_data2db --path /home/../../collect_view/DataCollection

Затем у меня возникла еще одна ошибка, связанная с путем, когда работник сказал, что не может найти таблицу базы данных, в которую я пытаюсь вставить данные.Поэтому я изменил шаг создания движка, добавив в него полный путь ...

base_url = '/home/.../collect_view/'
engine = create_engine ('sqlite:///' + base_url + 'app.db')

Эта проблема была еще более сложной для меня, так как мой работник уже работал в моем каталоге DataCollection, поэтому я подумал, что ('sqlite: ///../app.db ') будет правильным способом найти базу данных (как это было во время тестирования без работника rq).

Итак, после долгого объяснения мой вопрос: Как правильно управлять путями в этом случае?Мне кажется неправильным, что я должен использовать свой полный путь из / home ... Я что-то упускаю из-за того, как работают пути и / или rq работник (и тому подобное)?

Ниже приведены выдержки из моих файлов кода:

main_client.py

from redis import Redis
import rq
from collect_data import transfer

redis_url = Redis.from_url('redis://')  #(config['REDIS_URL'])
queue = rq.Queue('rq_worker-data2db', connection=redis_url)

#.....
#.....

def have_data(data):

    rq_job = queue.enqueue('collect_data.transfer', data)

#.....
#.....

collect_data.py

from base import Session, engine, Base
from tables import FieldData
import time
from datetime import datetime

def transfer(info):
    timestamp_in = datetime.utcnow()
    session = Session()
    data1 = FieldData(data=info, timestamp=timestamp_in)
    session.add(data1)
    session.commit()

base.py

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
base_url = '/home/.../collect_view/'
engine = create_engine ('sqlite:///' + base_url + 'app.db')
Session = sessionmaker(bind=engine)
Base = declarative_base()

tables.py

from sqlalchemy import  Column, String, Float, Integer, Date, DateTime, Table, ForeignKey
from base import Base
from datetime import datetime
# .....
#.....
class FieldData(Base):
    __tablename__ = 'field_data'
    id = Column(Integer, primary_key=True)
    data = Column(String(20))
    timestamp = Column(DateTime, index=True, default=datetime.utcnow)

    def __init__(self, data, timestamp):
        self.data = data
        self.timestamp = timestamp

В терминале я сначала запускаю Redis, а затем запускаю работника с:

$rq worker rq_worker_data2db --path /home/../../collect_view/DataCollection (где rq_worker_data2db - имя работника)

...