08:37 <foxmask> bonjello
10:27 <haypo> mathieui, gawel : salut. je ne suis pas au courant de soucis "_is_coroutine" + functools.partial
10:27 <haypo> mathieui, gawel : modifier functools pour qu'il ait connaissance d'asyncio me semble bizzare, s'il y a une modif à faire, ça serait plutôt dans _is_coroutine()
10:28 <haypo> gawel: http://pastealacon.com/36859 me semble louche car tu n'utilises pas call_soon_threadsafe()
10:28 <haypo> gawel: ça passe en mode debug avec une version récente d'asyncio ? (j'ai ajouté un thread "thread-safe" sur call_soon & cie)
10:31 <gawel> haypo: https://github.com/gawel/aiocron/commit/84cffb4bf0111d05459ae3af9c356454ffe629b9 :)
10:33 <gawel> je penses que y a pas besoin d'en avoir partout. juste pour le start() ou le .next()
10:34 <gawel> le reste est appellé depuis le thread, du coup. vu que ça se lance depuis un call_at
10:35 <haypo> gawel: ah, aiocron est ton projet :)
10:35 <gawel> ui
10:36 <haypo> gawel: tiens au passage, pourquoi faire un dossier qui ne contient qu'un __init__.py ? pourquoi ne pas créer un aiocron.py tout simplement ?
10:38 <gawel> parceque setuptools gère pas ca, je crois
10:38 <gawel> et puis ça grossis vite, ces machin la. pire que les gosses
10:38 <Adau> Coucou. Je reviens à la charge pour Bordeaux, même si les chances sont minces. Je vous ai envoyé un mail à orga@pycon.fr avec de plus amples détails et quelques questions ;)
10:38 <gawel> vaut mieux anticiper
10:38 <haypo> gawel: ah ? j'ai plusieurs projets "truc" avec "truc.py" et ça marche bien
10:39 <gawel> tu dois pas utiliser find_packages(), si ?
10:39 <NelleV> Adau: salut !
10:39 <gawel> d'ailleurs comme son nom l'indique, il trouve les paquet, pas les modules
10:39 <Adau> NelleV: coucou !
10:39 <haypo> gawel: https://bitbucket.org/haypo/aioeventlet/src/a5dc59846677945a329aa8fd79ff604e55289849/setup.py?at=default#cl-61
10:39 <NelleV> Adau: est-ce que je peux t'ajouter a la liste pyconfr orga ?
10:39 <haypo> gawel: py_modules=["aioeventlet"] pour copier aioeventlet.py
10:40 <gawel> oui, voila
10:40 <Adau> NelleV: bien sûr !
10:40 <NelleV> Adau: tu pourras ainsi voir les discussions
10:40 <haypo> gawel: avec ton truc de thread, du coup, @aiocron.crontab('*/30 * * * *') ne fonctionne pas
10:40 <gawel> pourquoi ?
10:40 <NelleV> (il n'y en a pas pour l'instant, mais on devrait bientôt faire la première réunion)
10:40 <gawel> ah oui
10:40 <gawel> non
10:41 <haypo> gawel: parce qu'il utilise asyncio.get_event_loop() qui est sûrement la mauvaise event loop
10:41 <gawel> faut lui passer la loop du thread crontab(loop=taloop)
10:41 <Adau> NelleV: Ok. Je ne compte pas m'imiscer dans vos discussions, mais je pourrai au moins répondre vite à tout le monde à propos de Bordeaux
10:41 <NelleV> Adau: en fait, j'ai zappé mon mdp admin… est-ce que tu peux t'inscrire ? qsub run.sh
10:41 <NelleV> qsub: submit error (Maximum number of jobs already in queue MSG=Job 1725633.torque.curie.fr violates the global server limit of 12000 jobs queued per user)
10:41 <NelleV> oups…
10:41 <NelleV> http://lists.afpy.org/listinfo/pyconfr-orga
10:41 <gawel> comme tu viole les queues
10:42 <NelleV> gawel: /o\
10:42 <gawel> j'aurai honte a ta place
10:42 <NelleV> gawel: quand est-ce que tu passes par Paris ?
10:42 <gawel> ce n'est pas prévu
10:42 <NelleV> il nous faut une excuse pour organiser un afpyro
10:42 <haypo> 12.000 jobs ça fait beaucoup
10:42 <mathieui> haypo, du coup j’ai un iscoroutine function qui ressemble à https://dpaste.de/jYAj/raw mais le souci c’est qu’une fonction qui décore une coroutine avec wraps() peut très bien ne pas retourner une coroutine
10:42 <NelleV> haypo: oui
10:42 <Adau> NelleV: C'est fait :)
10:43 <NelleV> haypo: quand les scripts sont mal écrit, cela fait tomber le cluster :D
10:47 <NelleV> Adau: merci !
10:47 <haypo> mathieui: hasattr(func, 'func') me semble peut fiable. tu peux écrire isinstance(func, functools.partial)
10:47 <haypo> mathieui: par contre, depuis python 3.4 y'a aussi isinstance(func, functools.partialmethod) (je n'ai pas vérifié si l'un hérite de l'autre)
10:48 <mathieui> ah, _functools.partial est une classe ? intéressant
10:49 <haypo> mathieui: la récursion sert à gérer functools.partial(functools.partial(...)) ?
10:49 <mathieui> ou autre wrapper, mais c’est possiblement inutile et peu performant
10:50 <haypo> mathieui: pour info, j'ai déjà des tests spécifiques functools.partial dans asyncio.events._get_function_source()
10:50 <haypo> mathieui: je vois que j'ai aussi utilisé la récursion, vu qu'il y a plein de if :) c'est plus clair qu'une boucle je pense
10:51 <haypo> mathieui: hum, en fait _get_function_source() est super compliqué :-p tu vas sûrement devoir faire un truc similaire. peut-être qu'il y a moyen de partager du code
10:51 <mathieui> ah oui, utiliser inspect.unwrap c’est plus malin
10:52 <haypo> mathieui: inspect.unwrap est différent, ça n'évite pas de devoir tester functools.partial
10:52 <haypo> mathieui: ça sert pour @functools.wraps()
10:52 <mathieui> (ça fait bizarre d’avoir un if _PY34: dans les sources incluses avec python 3.4 :D)
10:52 <haypo> mathieui: le code d'asyncio est un peu sale car c'est *exactement* le même code pour python 3.3, 3.4 et 3.5
10:53 <haypo> mathieui: juste faire des copier/coller est déjà compliqué à gérer, alors si en plus faut gérer des branches, laisser tomber :-p
10:53 <mathieui> haypo, ouais en fait faut reprendre _get_function_source mais s’arrêter quand on trouve un _is_coroutine au lieu d’arriver à la fonction toplevel
10:54 <haypo> mathieui: je me demande s'il ne faudrait pas rendre les tests iscoroutine() & iscoroutinefunction() conditionnels, ne tester qu'en mode debug
10:55 <haypo> mathieui: tiens, je demandais aussi s'il ne faudrait pas rendre le décorateur @coroutine obligatoire en mode debug
10:55 <mathieui> ce serait une bonne idée
10:57 <mathieui> (sinon, je sais pas trop comment structurer les parties où je parle d’asyncio dans ma doc, genre https://slixmpp.readthedocs.org/using_asyncio.html, il y a des bonnes pratiques à respecter ?)
11:14 <haypo> mathieui: j'ai ajouté une extension à Sphinx pour marquer les coroutines avec "coroutine" dans la doc : https://docs.python.org/dev/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_connection
11:14 <haypo> mathieui: les coroutines ont 2 marqueurs : "coroutine" tout au début, devant le prototype, et la phrase "This method is a coroutine"
11:15 <haypo> mathieui: iq.send(coroutine=True) ton API me semble bizzare :)
11:16 <haypo> mathieui: je préférerai avoir 2 méthodes différentes, ou alors passer cet argument au constructeur
11:17 <haypo> mathieui: python-ldap utilise par exemple LDAPObject (bloquant) et AsyncSearchHandler (asynchrone) http://www.python-ldap.org/doc/html/ldap-async.html
11:18 <haypo> (vieille bibliothèque, mais de mémoire l'API est mal trop mal)
11:18 <haypo> mathieui: ouvrir un ticket pour iscoroutinefunction() + functools.partial sur bugs.python.org stp
11:23 <mathieui> ok
11:24 <mathieui> (sinon pour l’API le souci c’est que cette méthode est réutilisée dans ~50 plugins, donc faudrait dupliquer également chaque fonction de chaque plugin qui l’utilise)
11:24 <haypo> mathieui: bah sinon tu peux utiliser 2 méthodes : send(), send_async()
11:25 <haypo> en général en python en évite de changer le type de retour selon un argument
11:25 <mathieui> bah oui, mais justement, ensuite dans les plugins faudrait tout dupliquer
11:25 <haypo> ex: os.getcwd() -> str, os.getcwdb() -> bytes
11:25 <mathieui> genre avoir un plugin.get_info() et un get_info_async()
11:25 <haypo> mathieui: ou alors tu fais du code systématiquement asynchrone :)
11:25 <mathieui> héhé
11:26 <haypo> mais si ton but est de merger ton code dans sleeptruc, vaut mieux garder les 2 API
11:26 <mathieui> haypo, note que le type de retour dans le cas où c’est pas fourni, on s’en fiche bien
11:26 <haypo> mathieui: bah oui, asyncio contamine un peu toute l'API :)
11:26 <mathieui> (si c’est pas fourni, ça retourne None)
11:26 <mathieui> (et ça schedule un callback)
11:27 <haypo> mais plutôt que de passer l'argument à chaque appel de méthode, ça me semblait mieux de le passer au constructeur
11:27 <haypo> enfin, pas trop le temps de lire ton code, c'était juste une remarque en passant ;)
11:27 <mathieui> pas de souci
11:34 <gawel> haypo: tu devrais en faire un package de ton extension sphinx. j'aimerai bien m'en servir sans recopier le code, moi
11:35 <gawel> voir le faire entrer dans sphinx, d'ailleurs
11:35 <gawel> faudrait que ça marche avec autodoc, idéalement
11:36 <gawel> eg: que :member: marque les coroutines
11:36 <haypo> gawel: le code est là https://hg.python.org/cpython/file/bb67b810aac1/Doc/tools/extensions/pyspecific.py#l123
11:36 <gawel> oui, je sais
11:36 <haypo> gawel: je te laisse le merger dans sphinx si tu veux, ça ne m'intéresse pas de le faire
11:36 <gawel> pff
11:37 <gawel> quel feignant, je te jure
11:39 <haypo> j'investie beaucoup d'énergie pour minimiser le travail que j'ai à faire :)
12:43 <GMLudo> haypo, gawel: +1 que ça devienne une extension sphinx et/ou intégré dans sphinx, je compte aussi l'utiliser
12:47 <GMLudo> BTW, haypo, j'ai publié le benchmark version complète: http://blog.gmludo.eu/2015/02/macro-benchmark-with-django-flask-and-asyncio.html
12:57 <gawel> GMLudo: ca serai marant de voir ce que ça donne avec aiowsgi :)
13:05 <gawel> et c'est ce que je disais, c'est que de la lecture
13:05 <gawel> ça va forcément plus vite :)
13:11 <Adau> Tiens, vous qui parlez d'asyncio depuis ce matin, vous savez pourquoi asyncio.Queue n'est pas threadsafe ? C'est dommage, on ne peut pas faire de "yield from q.get()" sur une queue qui serait remplie par un autre thread. C'est voulu ? C'est quoi la raison sous-jacente ?
13:11 <Adau> C'est dommage, ça me semblait super-pratique pourtant :(
13:12 <gawel> tu peux la remplir avec loop.call_soon_threadsafe
13:12 <Adau> oui, c'est ce que je fais... mais à force je commence à avoir des call_soon_threadsafe partout dans tout les sens
13:12 <gawel> héhé
13:13 <Adau> au final, je préfère utiliser queue.Queue et tricoter autour
13:13 <Adau> c'est largement moins dégueu
13:15 <Adau> Et du coup, je vois pas l'utilité de asyncio.Queue si c'est pas threadsafe: utiliser une queue dans un même thread où tourne une loop asyncio... J'ai du mal à saisir les cas particuliers d'utilisation
13:16 <Adau> Bref, ce serait pas grave du tout, si au moins c'était mentionné dans la doc Python: j'ai du perdre 1 heure avant de comprendre que c'était pas threadsafe :D
13:24 <mathieui> Adau, bah ça permet de faire des yield from queue.get/put
13:34 <haypo> Adau: asyncio est écrit pour n'utiliser qu'un thread, pourquoi as-tu besoin de plusieurs threads ? :)
13:34 <haypo> Adau: ah, si t'as des problèmes de doc, n'hésite pas à faire des suggestions, je peux les intégrer fissa
13:34 <haypo> Adau: (j'suis l'auteur de la doc, j'ai le droit de commit)
13:35 <haypo> Adau: tu peux utiliser queue.Queue pour dialoguer entre deux threads, puis écrire un glue pour mettre ça dans une asyncio.Queue
13:36 <haypo> Adau: (put dans queue.Queue le transmet dans la asyncio.Queue, ou un truc du genre)
13:39 <Adau> Désolé de la réponse tardive. En gros, j'ai des appels bloquants vers un script de calculs pure-python. Donc je pouvais utiliser un executor pour récupérer les résultats, mais une queue me paraissait plus simple et plus pratique
13:40 <Adau> en gros, je pensais attendre tranquilou le résultat avec yield from q.get()
13:40 <Adau> mais c'est pas la bonne approche
13:41 <Adau> donc soit j'utilise un thread avec un queue.Queue, soit un executor
13:41 <Adau> Mais l'approche un thread avec asyncio.Queue est clairement mauvaise
13:43 <Adau> haypo: la doc Python indique ceci: "asyncio locks and queues API were designed to be close to [...] the queue module, but they have no timeout parameter"
13:44 <Adau> Aucun mot sur le fait que asyncio.queue ne soit pas threadsafe
13:44 <haypo> Adau: ouais, faut aller chercher à la fin : https://docs.python.org/dev/library/asyncio-dev.html#concurrency-and-multithreading "...
13:44 <haypo> Most asyncio objects are not thread safe. ..."
13:44 <Adau> il faudrait indiquer un truc du genre "Additionnally, asyncio.Queue is not threadsafe and must be used inside a single thread asyncio loop"
13:45 <Adau> haypo: tu as tout à fait raison, c'est ce passage qui m'a donné la puce à l'oreille
13:46 <Adau> le probleme, c'est le "most" asyncio objects... Certains sont donc threadsafe, et quand on est un peu con comme moi, on pense tout de suite à queue = threadsafe
13:46 <linovia> A tout hasard, Arthur Lutz est-il sur le chan ?
13:46 <Adau> Peut-etre que certains ont l'habitude de faire du multithreading, et s'ils leur vient un jour d'utiliser asyncio, il risque d'avoir la même surprise
13:47 <Adau> Je pense qu'une simple phrase dans l'en-tête de cette doc suffirait largement: https://docs.python.org/3/library/asyncio-sync.html
13:48 <Adau> surtout que c'est précisé que ces API asyncio sont proches de celles des modules threading et queue, excepté pour les timeout... Donc je me suis dit que c'était la seule différence en fait :/
13:49 <Adau> J'ai pas testé, mais si ça se trouve, les lock et les event ne sont peut-être pas threadsafe non plus
13:51 <Adau> haypo: je sais pas trop comment te soumettre une correction. J'imagine sous forme de commit hg, mais je sais ni où, ni comment
13:56 <haypo> linovia: arthur est parfois connecté oui, mais je ne le vois pas là. son nick débute par "arth" :) je ne me souviens plus de la fin
13:56 <linovia> haypo: merci :)
14:25 <haypo> Adau: j'ai écrit https://hg.python.org/cpython/rev/14e7a28235c6
14:25 <haypo> Adau: j'ai ajouté "This class is no thread safe." à presque toutes les classes asyncio
14:29 <haypo> Adau: par contre, je n'ai pas touché aux verrous : asyncio.Lock & cie
14:29 <haypo> Adau: je ne sais pas si ces classes sont thread-safe ou pas ?!
14:34 <haypo> gawel, Adau, mathieui & cie : j'ai rejoint le salon #asyncio si vous voulez parler plus spécifiquement d'asyncio
14:39 <GMLudo> gawel: j'ai déjà pêté pas mal de temps sur le benchmark, je me suis limité à ce qui m'intéressait le +, j'ai très peu d'écriture
14:40 <GMLudo> gawel: à ce propos, le daemon complet de ce benchmark est en fait beaucoup de Panoramisk
14:40 <GMLudo> gawel: si un jour j'ai le courage de faire un benchmark sur ça, ça vaudrait la peine, mais ça intéressa quasi personne
14:41 <gawel> :)
14:42 <GMLudo> gawel: pour les perfs en écriture, pas certain que ça sera très différent. De toute façon, le prochain Framework Benchmark: http://www.techempower.com/benchmarks/ qui sortira le 16 mars aura une section pour API-Hour
14:42 <GMLudo> gawel: et dans ce bench, il y a des écritures
14:42 <GMLudo> gawel: l'écriture est faite par le pgsql, c'est lui qui prend tout
14:44 <GMLudo> gawel: par contre, le benchmark qui sortira le 16 mars n'aura pas autant de différences de perfs entre Flask, Django et API-Hour, parce que le benchmark ne tape pas assez fort
14:45 <GMLudo> suite à mes remarques, les gens qui font ce meta-benchmark devraient justement augmenter fortement la charge pour le benchmark d'après
15:45 <linovia> GMLudo: je vais jouer un peu avec ton bench ce soir
15:45 <linovia> et tuner un peu le django pour voir jusqu'où il peut monter ;)
15:46 <GMLudo> linovia: oui, bien sûr, avec plaisir :-) C'est principalement le but, si tu as de bonnes astuces, je suis preneur
15:46 <linovia> mettre un MAX_CONN_AGE pour la partie ORM et virer les middlewares déjà
15:52 <GMLudo> linovia: fais tout ce que tu veux ;-) En fait, je suis parti de la doc de déploiement de Django, histoire d'avoir les mêmes optimisations que la plupart des gens
15:53 <GMLudo> C'est peut-être justement une opportunité de faire un article sur comment booster un Django
15:54 <linovia> il en existe déjà plein ;)
15:54 <GMLudo> et je n'ai pas de stress à publier une nouvelle version du benchmark où le Django irait + vite après optimisations, dû moment que ce n'est pas des hacks ignobles qui ne sont pas prodables, genre réécrire en C des bouts de code
16:06 <linovia> GMLudo: on est en phase ;)
17:15 <alain_afpy> matin
21:51 <afpy_user|66108> Bonsoir