Runtime Python: recompilation et réutilisation de la bibliothèque C

Je développe un outil d’parsing numérique de fonctions définies par l’utilisateur. L’idée est de créer une interface utilisateur pratique en Python, dans laquelle l’utilisateur peut entrer une fonction C, puis appuyer sur un bouton – et recevoir des données de sortie. Les calculs pouvant prendre des minutes ou des heures, les performances uniquement numériques ne sont pas acceptables.

J’ai essayé l’approche suivante: l’interface utilisateur basée sur Python appelle gcc, comstack la dll à partir de fonctions utilisateur qui est plus utilisée que celle utilisée par mes principaux algorithmes basés sur C dans les wrappings Cython. Cela fonctionne, mais puisqu’il n’y a aucun moyen de décharger complètement le module python, je ne peux pas recomstackr une fonction définie par l’utilisateur tant que le programme de l’interface utilisateur n’est pas complètement fermé et exécuté à nouveau.

La seule façon dont je vois maintenant consiste à séparer les processus centraux de calcul et d’interface utilisateur, puis à les faire interagir via une mémoire / messagerie partagée. Lorsque l’utilisateur souhaite mettre à jour sa fonction, le programme termine le kernel, recomstack la DLL et redémarre le kernel.

Pouvez-vous suggérer une pratique courante dans de tels cas?

Je vous remercie!

Python a vraiment un bon support pour le multitraitement (et vraiment pas très bon pour les threads), vous pouvez donc créer un nouveau processus Python pour chaque expression à évaluer, comstackr et charger la dll dans le nouveau processus, puis le faire communiquer les résultats au processus parent. Lorsque le processus généré se termine, tout doit être déchargé.

Chaque fois que l’utilisateur entre une fonction, vous pouvez générer un nouveau module avec un nom unique et aléatoire (comme vous le feriez pour un fichier temporaire). Puis comstackz ce module, chargez-le et appelez la fonction.

Avec le temps, cela se traduira bien sûr par le chargement de nombreux modules. Si les utilisateurs n’exécutent pas trop de fonctions dans une même session, vous pourriez vous en tirer. Sinon, vous pouvez comstackr la fonction dans une DLL simple au lieu d’un module Python et la charger avec ctypes. Lorsque vous avez terminé avec la DLL, supprimez simplement toute référence à celle-ci – lorsque le handle de ctypes est finalement forcé, il doit décharger la DLL (voir Comment décharger une DLL à l’aide de ctypes dans Python? ).

Vous voudrez probablement aussi supprimer vos DLL du disque. Si vous utilisez Windows, cela peut être délicat, car il est difficile de prédire quand les types de fichiers vont le décharger, et Windows ne vous laissera pas le supprimer, il sera utilisé.

Avez-vous envisagé Weave ou Instant ( moins à jour )? Je ne l’ai utilisé que instantanément, mais il semble que ce serait parfait pour ce que vous décrivez.

Ils peuvent à la fois comstackr automatiquement et mettre en cache le code c au moment de l’exécution à partir d’une chaîne. Je n’ai jamais utilisé qu’instant pour inline c, mais je suis sûr que cela fonctionnerait aussi bien pour la compilation des entrées utilisateur.

Voici un exemple d’utilisation de weave, tiré du tutoriel .

>>> a = 'ssortingng' >>> def protected_printf(a): ... assert(type(a) == type(1)) ... weave.inline(r'printf("%d\n",a);',['a']) >>> protected_printf(1) 1 >>> protected_printf('ssortingng') AssertError...