Je suis censé répondre en 3 secondes.
Mon gestionnaire parle avec un serveur tiers, qui pourrait répondre en 3 secondes ou pas.
Je pense au code suivant - p>
class MainReply(webapp2.RequestHandler): def get(self): # do something # start task to talk with 3rd server for i in range(300): # wait 3 seconds # check task status # if finished, then break time.sleep(0.01) # if not finished, inform user
Est-ce une approche correcte? Ou y a-t-il une meilleure solution?
Mettre à jour. Je travaille sur le bot Voice Assistant (quelque chose de similaire à Google Assistant), où le bot doit répondre dans les 3 secondes. Et le bot ne peut pas lancer la réponse lui-même, c'est-à-dire que je ne peux pas donner une autre réponse, une fois la demande terminée. Et comme il s'agit d'un assistant vocal, je ne peux pas donner de lien. Je pensais à l'approche suivante - si je peux donner une réponse normale en 3 secondes, donnez-la. Sinon, demandez à l'utilisateur de demander à nouveau avec un mot simple comme "Statut".
3 Réponses :
La règle de base est que vous ne devriez jamais faire un pool comme décrit dans votre article car (1) vous bloquez "manuellement" plus de ressources que nécessaire (2) vous gâchez votre code en simulant un code asynchrone qui ne l'est vraiment pas, et (3) Les langages fournissent généralement des outils pour gérer la programmation simultanée, qui sont spécialement conçus pour ce type de tâches, et cela fait le travail pour vous bien mieux que vous ne pourriez l'implémenter (dans la plupart des cas).
En suivant vos besoins. J'ai écrit un programme simple que vous pouvez tester. Consultez ici asyncio.wait_for code > documentation. Trouvez ici également un guide utile vers async.
Copiez le code dans un fichier et exécutez $ python [filename]
import asyncio import random from concurrent.futures._base import TimeoutError async def safe_get(): result = "I'm currently out of my office." try: result = await asyncio.wait_for(get(), 3) except TimeoutError as e: print("Responder thought too much about his answer") return result async def get(a=1,b=6): random_time = random.randint(a,b) await asyncio.sleep(random_time) return "I'm doing good thanks! Sorry it took me " + str(random_time) + "s to answer." async def main(): # Toggle comment on the two following lines to see (1) unwanted behaviour and (2) wanted behaviour # response = await get() response = await safe_get() print(response) if __name__ == "__main__": asyncio.run(main())
Merci. Mais j'ai peur que cela ne fonctionne pas avec Google App Engine ... Mais voici l'option - cloud.google.com/appengine/docs/standard/python/…
Donc ça ne marchera pas, pourquoi? Je dois rater quelque chose. Le lien que vous envoyez indique "Pour émettre une requête asynchrone, votre application doit: ..." Et vous y trouverez également des instructions qui vous indiquent comment définir un délai d'expiration dans votre requête. Je ne peux pas exécuter le code google-api, mais cela me semble assez similaire. Pouvez-vous m'indiquer ce qui rend cette tâche impossible?
Désolé, je n'ai pas mentionné au départ que j'utilise Python 2.7. Et voici la confirmation que cela ne fonctionne pas - stackoverflow.com/questions/53719006/... .
Et qu'est-ce qui vous empêche d'utiliser l'extrait de code dans la réponse à ce message, ainsi que la date limite code> du paramètre
urlfetch.create_rpc ()
indiqué dans le docs ?
Hormis une expérience utilisateur douteuse - réponse lente et potentiellement pas la réponse attendue par vos utilisateurs - une telle approche pose un risque pour l'intégrité de votre serveur: pour chaque requête en attente, votre serveur utilisera des ressources et en cas de forte entrée Le pic des demandes peut s'exécuter sur son pool ou ses ressources disponibles (si elles sont limitées) ou peut augmenter vos coûts (par exemple en lançant des instances supplémentaires pour suivre les autres demandes entrantes s'il est configuré pour une mise à l'échelle automatique). p >
En général, pour les demandes qui peuvent prendre du temps, il est préférable de répondre immédiatement avec un identifiant de demande en attente et des URL complémentaires où le client peut vérifier l'état de la demande et éventuellement obtenir la réponse attendue, lorsqu'elle est disponible. Votre serveur prendrait soin - en arrière-plan, et non sur le thread de demande entrante d'origine - d'obtenir la réponse du serveur tiers. De cette façon, vous pouvez traiter tout type de demande qui peut prendre beaucoup de temps pour obtenir la réponse, que ce soit d'une tierce partie ou d'un traitement interne.
Merci, Dan. Permettez-moi de vous donner plus de détails - je travaille sur le bot Voice Assistant (quelque chose de similaire à Google Assistant), où le bot doit répondre dans les 3 secondes. Et le bot ne peut pas lancer la réponse lui-même, c'est-à-dire que je ne peux pas donner une autre réponse, une fois la demande terminée. Et comme il s'agit d'un assistant vocal, je ne peux pas donner de lien. Je pensais à l'approche suivante - si je peux donner une réponse normale en 3 secondes, donnez-la. Sinon - demandez à l'utilisateur de demander à nouveau avec un mot simple comme "Statut".
Parlez-vous à ce serveur tiers via http? pouvez-vous simplement utiliser le paramètre timeout
dans les requêtes python?
class MainReply(webapp2.RequestHandler): def get(self): # do something try: r = requests.post(... , timeout=3) # finished, inform user except requests.exceptions.Timeout: # not finished, inform user
Pour ce qui est des principes fondamentaux de la programmation, je dirais que ce ne serait jamais l'approche. Vous devez rechercher les abonnements aux événements et les modèles d'observateurs et si le langage ne les fournit pas par défaut, vérifiez les options disponibles < / a>.
@MikeMajara, merci, mais je ne pense pas que cela fonctionnera dans mon cas. Disons que je m'abonne à l'événement d'achèvement de la tâche. Mais cela peut arriver avant 3 secondes ou après. Comment cela aidera-t-il? Je peux répondre à l'utilisateur seulement en 3 secondes.
Qu'entendez-vous par répondre à l'utilisateur seulement en 3 secondes? Si la réponse est là dans <3s: rendez-la; sinon renvoyer une erreur?
Sinon - renvoyez une autre réponse.