Suggerirei di utilizzare una classe di base attività astratta e di memorizzare nella cache requests.session
.
Dalla documentazione di sedano:
Un compito non viene creata un'istanza per ogni richiesta, ma è registrato nel Registro di sistema compito come istanza globale.
Ciò significa che il costruttore __init__ verrà chiamato una sola volta per processo e che la classe di attività è semanticamente più vicina a un attore.
Questo può anche essere utile per memorizzare le risorse in cache ...
import requests
from celery import Task
class APITask(Task):
"""API requests task class."""
abstract = True
# the cached requests.session object
_session = None
def __init__(self):
# since this class is instantiated once, use this method
# to initialize and cache resources like a requests.session
# or use a property like the example below which will create
# a requests.session only the first time it's accessed
@property
def session(self):
if self._session is None:
# store the session object for the first time
session = requests.Session()
session.auth = ('user', 'pass')
self._session = session
return self._session
Ora, quando si creano le attività che renderanno le richieste API:
@app.task(base=APITask, bind=True)
def call_api(self, url):
# self will refer to the task instance (because we're using bind=True)
self.session.get(url)
Inoltre è possibile passare le opzioni di autenticazione API utilizzando il app.task
decoratore come un argomento in più che sarà ospitato al __dict__
del compito, per esempio:
# pass a custom auth argument
@app.task(base=APITask, bind=True, auth=('user', 'pass'))
def call_api(self, url):
pass
e rendere la classe base usa la passata una opzioni, ossia l'autenticazione:
class APITask(Task):
"""API requests task class."""
abstract = True
# the cached requests.session object
_session = None
# the API authentication
auth =()
@property
def session(self):
if self._session is None:
# store the session object for the first time
session = requests.Session()
# use the authentication that was passed to the task
session.auth = self.auth
self._session = session
return self._session
Si può leggere di più sul sito docs Sedano:
Ora torniamo alla tua domanda iniziale che sta passando argomenti extra al worker dalla riga di comando:
C'è una sezione su questo nei documenti di sedano Adding new command-line options, ecco un esempio di passaggio di un nome utente e una password per il lavoratore dalla riga di comando:
$ celery worker -A appname --username user --password pass
Il codice:
from celery import bootsteps
from celery.bin import Option
app.user_options['worker'].add(
Option('--username', dest='api_username', default=None, help='API username.')
)
app.user_options['worker'].add(
Option('--password', dest='api_password', default=None, help='API password.')
)
class CustomArgs(bootsteps.Step):
def __init__(self, worker, api_username, api_password, **options):
# store the api authentication
APITask.auth = (api_username, api_password)
app.steps['worker'].add(CustomArgs)
Eccellente, stavo avendo difficoltà a decifrare tutto ciò dalla documentazione. Grazie per averlo esposto così bene. –
Mi dispiace di approfondire ancora una volta, saresti in grado di chiarire come passare gli argomenti della riga di comando da Boostep all'inizializzazione dell'attività (in modo da poter inizializzare l'oggetto della sessione Attività con il nome utente e la password forniti dal comando -linea). L'obiettivo è non memorizzare le credenziali API in testo semplice. –
@JoshuaGilman scusa per il ritardo, ho aggiornato la risposta con un esempio. – Pierre