OVH Cloud OVH Cloud

scripting via Python et gros fichiers

22 réponses
Avatar
Rémi Hérilier
Bonjour,

Je suis en train d'étudier la possibilité d'utiliser Python comme
langage de script dans un programme en C++. En fait, le script Python me
servira à stocker des données pour mon programme et se présentera sous
la forme d'une suite de commande.

Mes quelques tests m'ont montré que Python lit/compile d'une traite
le fichier Python et ne l'éxécute qu'une fois la lecture/compilation
finie. Un essai sur un fichier de 15 Mo m'a contraint à tuer le
processus qui avait bouffé mes 512 Mo de ram et 1 Go de swap.

Mon test est très bête puisqu'il utilise PyParser_SimpleParseFile mais
après avoir lu la doc et fait tourner Google (et essayé 2 ou 3 trucs à
moitié compris), je n'ai finalement pas trouvé comment dire à Python
qu'il devait évaluer mon script pas à pas.

À part charger à la main une commande complète puis la passer à
PyParser_SimpleParseString, je ne vois pas trop.

De plus, le fait d'avoir un langage complet (boucle for, if, etc) serait
appréciable pour pouvoir tester le comportement de mon programme.

Avec cette possibilité là, extraire une commande pour l'éxécuter est
autre chose qu'un banal fgetline. En effet, il faudrait, par exemple,
extraire un bloc for en entier, chose qui me semble bien ardue.

Bref, je reste dubitatif ... utiliser Python (ou tout autre langage de
script) est-il une bonne idée ...

Les avis de gens plus experts ou plus avisés sont les bienvenus.


cordialement

Rémi Hérilier

10 réponses

1 2 3
Avatar
Paul Gaborit
À (at) Fri, 13 May 2005 16:34:54 +0200,
Paul Gaborit écrivait (wrote):
Dans votre programme, vous utilisez python ou C++ pour parser les données et
lorsque vous rencontrez la description d'un nouveau type alors vous dégainez
votre interpréteur/compilateur python pour l'ajouter dynamiquement...
L'intérêt serait de limiter la partie code dynamique aux seuls endroits
vraiment utiles.


Reste tout de même un "petit" problème de sécurité : comment et jusqu'où faire
confiance à du code qui provient d'un fichier externe ? Les macro-virus
existent déjà : je pense que ce n'est plus brevetable ;-)

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>

Avatar
Rémi Hérilier
Paul Gaborit wrote:
À (at) Fri, 13 May 2005 11:45:43 +0200,
Rémi Hérilier écrivait (wrote):

Mais je pense que je vais me rabattre sur un parser à la mano (adieu les
facilités d'un langage de programmation) et passer par un script d'export
pour Blender.



Ce qui serait peut-être envisageable, ce serait un format de fichier purement
descriptif (en XML ou en texte pur) ouvert... Ouvert dans le sens où vous
pourriez y ajouter de nouveaux types (ou commandes) dynamiquement décrits en
python.

Dans votre programme, vous utilisez python ou C++ pour parser les données et
lorsque vous rencontrez la description d'un nouveau type alors vous dégainez
votre interpréteur/compilateur python pour l'ajouter dynamiquement...
L'intérêt serait de limiter la partie code dynamique aux seuls endroits
vraiment utiles.



L'idée est intéressante mais je n'ai aucunes idées de comment le faire =)
De plus, comme dit dans un autre post, j'utilise python pour faire
quelquechose pour lequel il n'est pas fait. Autant arrêter les frais
tout de suite.

Je vais finalement opter pour un parser perso.

Certes je réinvente encore une fois la roue dans la longue histoire des
parsers mais ayant dans l'optique de traiter des volumes de données bien
plus gros que 15 Mo, avoir un parser dont je contrôle le fonctionnement
sera très certainement bénéfique.

Pour ton interrogation sur la sécurité vis à vis du code externe, il
s'agit du même problème qu'exécuter un programme sans s'assurer de son
origine. S'il existait un moyen pour contrer la bétise humaine, on
aurait moins de problème :))

merci encore pour ton aide ;)

bon week end à tous o/

Rémi Hérilier


Avatar
F. Petitjean

Sur comp.lang.python vous auriez droit à des commentaires du genre Ick
et 'yuck'.


j'en conviens :))

mais si je suis là, c'est pour trouver une solution convenable ;)


Oui on va y arriver.


Je ne vois pas de code python,


il n'y a absolument rien de caché. On m'a demandé un exemple de fichier,
je l'ai donné :))

plus sérieusement, ce qui peut manquer, c'est l'init du bouzin qui
ajoute à Python ma vingtaine de fonction :

--- début ---

static PyMethodDef crbn_methods[] = {
...
{NULL, NULL, 0, NULL}
};

void py_binding_init( crbn_context_t* ctx )
{
PyObject *m, *d;
PyObject *pcc = PyCObject_FromVoidPtr( ctx, NULL );

Py_Initialize();

m = PyImport_AddModule( "__builtin__" );
d = PyModule_GetDict( m );
PyDict_SetItemString( d, PYCRBNCONTEXT, pcc );

m = Py_InitModule( "crbn", crbn_methods );

PyRun_SimpleString( "from math import *n" );
PyRun_SimpleString( "from crbn import *n" );
}

--- fin ---

(J'ai un peu honte des 2 PyRun_SimpleString mais Blender le fait
alors bon=)


Faut pas avoir honte. Mais si le fichier généré est vraiment du python
pourquoi ne pas y mettre les instructions magiques
from math import * #et je doute d'ailleurs de l'intérêt de cett ligne
from crbn import *

Sur la base du mot clé 'crbn' (+ python bien entendu) je découvre
http://rem.planet-d.net/crbn/index.html
et pas de téléchagrment actuellement. Hum! avec rem comme Rémi, tiens
tiens.

et peut être ma façon de lancer de charger les données :

-- debut ---

fp = fopen( filename, "r" );
PyRun_SimpleFile( fp, filename );
fclose( fp );

--- fin ---

mais je doute que ça fasse avancer le schmilblick.

Blague à part, faut trouver un moyen pour passer les paramètres de ces
fonctions depuis le code C++ vers un interpréteur Python embarqué
(embedded?) directement, pas à coup d'eval ou de PyRun_Jenesaispasquoi.
Les possibilités de faire ce lien sont multiples :
swig, SIP, boost_python, etc .
Les paramètres seront passés en binaire et comme ce sont en majorité des
chiffres cela devrait aller nettement mieux.


ça serait une idée mais je cherche à n'avoir qu'un seul fichier pour
contenir les données.

J'vais reessayer avec flex/bison et si ça me plante toujours entre les
doigts, j'attaquerai un parser à la mano.


C'est l'hôpital qui se moque de la charité. Il semblerait que vous soyez
capable de concevoir, de documenter et d'implémenter la génération d'un
fichier ASCII (http://rem.planet-d.net/crbn/csf.html) mais qu'il y a un
blocage pour avoir les mêmes informations en bianire.
Avant donc de sortir la grosse artillerie flex/bison (qui sert à
'parser' des fichiers textes, je vous conseille de réfléchir à un format
binaire de fichier contenant les mêmes informations. Python est capable
de lire des fichiers binaires vous savez.

Par exemple vous avez beaucoup de triangles définis avec un code v suivi
de 9 chiffres, vous pouvez coder le type de l'objet sur un entier (ou
même sur deux octets) et les paramètres suivents (c'est vous qui voyez)
dans le script python vous déterminer à partir du type entier lu le
nombre de paramètres attachés et vous lisez les paramètres
import struct
help(struct.unpack)

Note
[1] en regardant le nom des fonctions, il n'y aurait pas un from
blender import * au début du fichier ?


non je développe un raytracer indépendant de tout logiciel de
modélisation mais un script d'export est prévu pour Blender ;)

merci encore

Rémi Hérilier


--
Il y en a qui ont essayé, ils ont des problèmes, cela dit il est très
rapide. (Laspalles)


Avatar
Rémi Hérilier
F. Petitjean wrote:

Sur comp.lang.python vous auriez droit à des commentaires du genre Ick
et 'yuck'.


j'en conviens :))

mais si je suis là, c'est pour trouver une solution convenable ;)



Oui on va y arriver.


Je ne vois pas de code python,


il n'y a absolument rien de caché. On m'a demandé un exemple de fichier,
je l'ai donné :))

plus sérieusement, ce qui peut manquer, c'est l'init du bouzin qui
ajoute à Python ma vingtaine de fonction :

--- début ---

static PyMethodDef crbn_methods[] = {
...
{NULL, NULL, 0, NULL}
};

void py_binding_init( crbn_context_t* ctx )
{
PyObject *m, *d;
PyObject *pcc = PyCObject_FromVoidPtr( ctx, NULL );

Py_Initialize();

m = PyImport_AddModule( "__builtin__" );
d = PyModule_GetDict( m );
PyDict_SetItemString( d, PYCRBNCONTEXT, pcc );

m = Py_InitModule( "crbn", crbn_methods );

PyRun_SimpleString( "from math import *n" );
PyRun_SimpleString( "from crbn import *n" );
}

--- fin ---

(J'ai un peu honte des 2 PyRun_SimpleString mais Blender le fait
alors bon=)



Faut pas avoir honte. Mais si le fichier généré est vraiment du python
pourquoi ne pas y mettre les instructions magiques
from math import * #et je doute d'ailleurs de l'intérêt de cett ligne
from crbn import *


Le fichier est bien du Python, sinon je ne serai pas sur fclp ;)

Python n'est pas le premier langage que je teste, avoir un format de
fichier neutre de tout langage sous-jacent est donc tout à fait normal.
En plus, les 'from XXX import *' sont des invariants par rapport au
format de fichier, leurs place est donc dans le code C++.

Sinon, "from crbn import *" a un intérêt non négligeable : un appel à
py_InitModule ne fait qu'initialiser un module et rien de plus (donc pas
d'importation du module dans __main__ et encore moins d'importation des
objets du dit module).

Sur la base du mot clé 'crbn' (+ python bien entendu) je découvre
http://rem.planet-d.net/crbn/index.html
et pas de téléchagrment actuellement. Hum! avec rem comme Rémi, tiens
tiens


vous m'avez démasqué ;)


et peut être ma façon de lancer de charger les données :

-- debut ---

fp = fopen( filename, "r" );
PyRun_SimpleFile( fp, filename );
fclose( fp );

--- fin ---

mais je doute que ça fasse avancer le schmilblick.


Blague à part, faut trouver un moyen pour passer les paramètres de ces
fonctions depuis le code C++ vers un interpréteur Python embarqué
(embedded?) directement, pas à coup d'eval ou de PyRun_Jenesaispasquoi.
Les possibilités de faire ce lien sont multiples :
swig, SIP, boost_python, etc .
Les paramètres seront passés en binaire et comme ce sont en majorité des
chiffres cela devrait aller nettement mieux.


ça serait une idée mais je cherche à n'avoir qu'un seul fichier pour
contenir les données.

J'vais reessayer avec flex/bison et si ça me plante toujours entre les
doigts, j'attaquerai un parser à la mano.



C'est l'hôpital qui se moque de la charité.


Je vais faire mine de ne pas avoir lu ...

Il semblerait que vous soyez
capable de concevoir, de documenter et d'implémenter la génération d'un
fichier ASCII (http://rem.planet-d.net/crbn/csf.html) mais qu'il y a un
blocage pour avoir les mêmes informations en bianire.


Le format de fichier que j'ai défini est aussi bien exprimable en
binaire qu'en texte. Je ne vois vraiment où vous voyez un blocage.

Avant donc de sortir la grosse artillerie flex/bison (qui sert à
'parser' des fichiers textes, je vous conseille de réfléchir à un format
binaire de fichier contenant les mêmes informations. Python est capable
de lire des fichiers binaires vous savez.


Par exemple vous avez beaucoup de triangles définis avec un code v suivi
de 9 chiffres, vous pouvez coder le type de l'objet sur un entier (ou
même sur deux octets) et les paramètres suivents (c'est vous qui voyez)
dans le script python vous déterminer à partir du type entier lu le
nombre de paramètres attachés et vous lisez les paramètres
import struct
help(struct.unpack)


Utiliser quelquechose de surdimensionné par rapport à ses besoins est
effectivement qualifiable de "grosse artillerie". Mon besoin étant de
parser des fichiers textes, flex/bison est donc parfaitement adapté. Le
seul problème est que le code qu'ils me générent plante. Si j'ai essayé
Lua puis Python, ce n'est que pour remplacer flex/bison.

Le format binaire est effectivement une idée et elle a été envisagée
bien avant que la première ligne de code soit écrite. Le choix s'est
simplement porté sur un format texte.

Pour en venir à votre solution, elle semble reposer sur l'hypothèse que
Crbn est un ensemble regroupant un(des) programme(s) écrit(s) en Python
et un(des) module(s) contenant mon code de génération d'image. Ce n'est
pas du tout le cas. Je le répète, je fais des essais avec Python comme
langage de description de scène.

Par contre, utiliser Python pour parser un format binaire et envoyer les
données à mon code C++, c'est vraiment sortir la grosse artillerie pour
pas grand chose.

Bref. Pour revenir sur le sujet initial. L'API de liaison Python/C ne
permet pas de lire/exécuter incrémentalement un fichier. Tant pis pour
moi, j'irai donc voir ailleurs.

cordialement

Rémi Hérilier



Avatar
F. Petitjean

Bref. Pour revenir sur le sujet initial. L'API de liaison Python/C ne
permet pas de lire/exécuter incrémentalement un fichier. Tant pis pour
moi, j'irai donc voir ailleurs.


Ah bon ? les méthodes file.read(size), file.write(data) et
file.readline() ne sont pas diponibles avec « l'API de liaison
Python/C » ? Cela m'étonne fortement mais comme je n'ai jamais utilisé
ke veux bien vous croire. Un message sur comp.lang.python avec une
description un peu plus précise du design de votre application serait
peut-être à envisager.

Je ne comprends pas du tout ce qui vous empêche de doubler l'écriture
sur fichier de la scène (binaire ou ASCII) d'appels (incrémentaux) aux
fonctions python correspondantes ? (je suis un peu perdu sur ce qui est
en C++ et ce qui est en python, qu'est-ce qui génère la scène, qui la
stocke, qui l'affiche éventuellement ). D'autre part, lisez la
documentation OpenGL sur « triangle strip » et « quad strip » vous
devriez pouvoir économiser le passage de coordonnées redondantes.

cordialement

Rémi Hérilier


Avatar
Frédéric Momméja
Bonjour,

pardon de reprendre un peu tardivement ce fil,

Rémi Hérilier écrivait le 13/05/05 11:45 :
kaerbuhez wrote:

Si oui, c'est ça que je changerais. Si tu mets tes données dans un
fichier parsable facilement (module csv par exemple) et ton code
python dans un autre que tu interfaces avec ton code C++, je pense que
ton probléme est résolu et tu peux utiliser toute la puissance de Python.



Justement, j'aimerai conserver tout dans un seul fichier :/


Tu pourrais très bien tout garder dans un seul fichier et générer,
uniquement durant la phase de traitement de celui-ci, un fichier
temporaire ne contenant que le code Python à exécuter. ;)

--
Frédéric Momméja


Avatar
Rémi Hérilier
F. Petitjean wrote:

Bref. Pour revenir sur le sujet initial. L'API de liaison Python/C ne
permet pas de lire/exécuter incrémentalement un fichier. Tant pis pour
moi, j'irai donc voir ailleurs.



Ah bon ? les méthodes file.read(size), file.write(data) et
file.readline() ne sont pas diponibles avec « l'API de liaison
Python/C » ? Cela m'étonne fortement mais comme je n'ai jamais utilisé
ke veux bien vous croire. Un message sur comp.lang.python avec une
description un peu plus précise du design de votre application serait
peut-être à envisager.


Je ne dis pas que file.read(size) & compagnie n'existe pas, je dis que
Python ne peut pas lire/exécuter incrémentalement un fichier.

Faites vous une programme (en Python ou en C) qui lit et exécute un
script Python ligne à ligne et vous verrez par vous même que vous avez
de grandes chances d'avoir des SyntaxError de partout ; entre autre dans
les cas suivants :
- un appel de fonction sur plusieurs lignes,
- les blocs (def, for, if, etc.).

Et pourquoi donc ? La ligne n'est pas une entité manipulable par un
compilateur, il lui est préféré la déclaration (le terme "statement" que
l'on peut lire dans la plupart des grammaires de langage de programmation).

Donc pour conserver les avantages de Python (un langage de programmation
contrairement à un parser de fichier texte), il me faudrait extraire
soit les appels complets aux fonctions (on évite ainsi le fait qu'ils
soient écrits sur plusieurs lignes), soit extraire les blocs avant de
les exécuter (pour éviter les problèmes de syntaxe dûs au concept de
bloc d'instructions).

Après un court moment de réflexion, on se dit que c'est parfaitement
faisable en Python. Par contre, le problème initial n'est toujours pas
résolu. Pour rappel, c'est les difficultés de Python à manipuler de gros
scripts et à fortiori de grosses déclarations. En effet, un maillage
conséquent (plusieurs dizaine de milliers de faces) représente, en
ASCII, plusieurs Mo. Je me retrouverai donc dans le même cas que
demander à Python de me digérer un fichier de 15 Mo.

Ce sont toutes ces considérations qui me font dire que Python n'est pas
adapté à l'utilisation que je voudrais en faire. Je ne cherche ni à
troller ni à dénigrer Python. Je cherche juste une solution viable et
efficace à mon problème. D'ailleurs Python est le seul langage qui
semble convenir pour implémenter les shaders programmables de Crbn (pour
plus d'infos, chercher sur google "renderman shader", "GLSL" ou encore
"HLSL").

Je ne comprends pas du tout ce qui vous empêche de doubler l'écriture
sur fichier de la scène (binaire ou ASCII) d'appels (incrémentaux) aux
fonctions python correspondantes ? (je suis un peu perdu sur ce qui est
en C++ et ce qui est en python, qu'est-ce qui génère la scène, qui la
stocke, qui l'affiche éventuellement ).


Qu'entendez vous par "doubler l'écriture" ? Gérer un format textuel ET
un format binaire dans Crbn ? Si tel est le cas, je vous répète qu'il
n'y a aucunes difficultés pour gérer un format ou l'autre. L'utilisation
d'un format binaire est difficile à appréhender sans avoir
de logiciels pour le manipuler. D'ailleurs, ce format n'est pas un
format fait pour stocker des informations d'animation ou autres
méta-informations sur la scène (les formats .ma ou .mb de Maya, les
.blend de blender sont là pour ça). Il n'est qu'un flux de données pour
le moteur de rendu qu'est Crbn. À terme, un format binaire sera prévu
(pour du stockage volumineux (pas mes 15 misérables Mo) ou pour envoyer
les données aux noeuds d'une ferme de rendu).

Pour vous éclairer sur la structure de Crbn, il se présente sous la
forme d'une bibliothèque (libcrbn) qui centralise l'intégralité du
processus : lecture d'une scène depuis un fichier, écriture d'un scène
dans un fichier, stockage des données et mécanisme de génération de
l'image finale. La visualisation est faite via un programme externe.
Libcrbn utilise un ensemble de modules pour donner un sens au données.
Elle ne sait donc pas ce qu'est une quadrique ou un maillage,
l'algorithme de Whitted ou celui nommé Metropolis Light Transport ;
juste que les premiers sont des primitives géométriques et les seconds
des algorithmes d'illumination.

Après, n'importe qui peut ajouter un greffons à blender, maya, 3dsmax,
ou softimage pour qu'il exploite libcrbn pour effectuer le rendu des
images. Pour ma part, J'ai un programme en ligne de commande pour lancer
l'interprètation d'un fichier de scène.

(c'est tellement bien écrit que j'vais mettre à jour ma page oueb;)

Pour que libcrbn puisse lire une scène, elle intégre donc un
interpréteur (en flex/bison au début, Lua par la suite, Python à l'heure
actuelle et dans un futur proche un parser maison) auquel j'ajoute des
fonctions pour qu'il fasse appel à l'API de Crbn. L'interpréteur est
interne à libcrbn, nous ne sommes donc pas, en considérant Python comme
l'interpréteur, dans le cas de PIL ou de PyXML qui sont des extensions à
Python installées dans /usr/lib/python$VERSION/site-packages/...

Je me permet de revenir sur le choix d'un parser. Il n'est pas facile
(surtout dans le cas de gros volumes de donnée). En dehors des
limitations de chaque langage, l'utilisation mémoire est une chose
importante à considérer. En effet, si on utilise un langage (Lua,
Python, Ruby ou autre), il faut savoir que l'on a généralement des
duplications d'informations : lors de la phase de lecture, dans
l'interpréteur même et dans son propre programme.

un langage qui lit/exécute un fichier pas à pas (à savoir lit une
déclaration, la compile, l'exécute puis l'oubli) permet de réduire les 2
premiers cas mais pas de les supprimer. On ne fait que repousser le
problème. Un déclaration de 100 Mo utilisera toujours 300 Mo (je
schématise;)

C'est pourquoi je me rabats sur un interpréteur incrémental (qui utilise
une quantité fixe et réduite de mémoire pour l'interprétation et ne fait
aucunes duplications). Dans l'absolu, c'est la meilleure solution.

D'autre part, lisez la
documentation OpenGL sur « triangle strip » et « quad strip » vous
devriez pouvoir économiser le passage de coordonnées redondantes.


Vous avez été suffisamment débrouillard pour trouver la page Internet de
mon projet, lisez le donc en entier (rubrique «modules» pour vous
aiguiller) et vous comprendrez que l'objet de type «triangle» est la
seule entité actuellement implémentée pour gérer ce qui relève de
modélisation à base de triangle. Un objet de type «maillage» (avec les
optimisations qui vont biens) est juste à faire :)

Ça fait une bonne dizaine d'années que mes lectures et mes programmes
tournent autours de la synthèse d'image et «seulement» depuis 5 ans pour
ce qui est du lancer de rayons. J'ose espérer que vous me faites
confiance quant à mes choix :)

cordialement

Rémi Hérilier




Avatar
F. Petitjean
F. Petitjean wrote:

Je ne dis pas que file.read(size) & compagnie n'existe pas, je dis que

Python ne peut pas lire/exécuter incrémentalement un fichier.

Faites vous une programme (en Python ou en C) qui lit et exécute un
script Python ligne à ligne et vous verrez par vous même que vous avez
de grandes chances d'avoir des SyntaxError de partout ; entre autre dans
les cas suivants :
- un appel de fonction sur plusieurs lignes,
- les blocs (def, for, if, etc.).


Je ne vous le fais pas dire. C'est vous qui voyez. Il y en a qui ont
essayé. Ils ont eur des problèmes. Cela dit, il est très rapide (air
connu)

[snip]


Je ne comprends pas du tout ce qui vous empêche de doubler l'écriture
sur fichier de la scène (binaire ou ASCII) d'appels (incrémentaux) aux
fonctions python correspondantes ? (je suis un peu perdu sur ce qui est
en C++ et ce qui est en python, qu'est-ce qui génère la scène, qui la
stocke, qui l'affiche éventuellement ).


Qu'entendez vous par "doubler l'écriture" ? Gérer un format textuel ET
un format binaire dans Crbn ?


Non! J'ai écrit *ou*. Ce que je voulais dire, c'est qu'au moment ou vous
avez (j'essaie de deviner, si vous insériez un peu de code ou de
pseudo-code dans votre message ce serait plus clair):
line = 'object ( "triangle", "v", [ unechieede.3f ])' % coords
fichier_scene.write(line)
Pourquoi ne pas envoyer à crbn ou libcrbn un appel de fonction
personnalisé avec les paramètres adéquats ? Parce que vous avez décidé
que crbn ne serait utilisable qu'en passant par un script python ?


Si tel est le cas, je vous répète qu'il
n'y a aucunes difficultés pour gérer un format ou l'autre. L'utilisation
d'un format binaire est difficile à appréhender sans avoir
de logiciels pour le manipuler.


Je ne vous le fais pas dire. C'est vous qui voyez. Il y en a qui ont
essayé. Ils ont eur des problèmes. Cela dit, il est très rapide.

D'ailleurs, ce format n'est pas un
format fait pour stocker des informations d'animation ou autres
méta-informations sur la scène (les formats .ma ou .mb de Maya, les
.blend de blender sont là pour ça). Il n'est qu'un flux de données pour
le moteur de rendu qu'est Crbn.


Si vous aviez commencé votre message par là !
Donc, pas moyen d'exprimer le flux de données (et la sémantique
associée) autrement que par des appels à des fonctions Python du module
crbn ? Vous voyez le goulot d'étranglement ?

À terme, un format binaire sera prévu
(pour du stockage volumineux (pas mes 15 misérables Mo) ou pour envoyer
les données aux noeuds d'une ferme de rendu).

Pour vous éclairer sur la structure de Crbn, il se présente sous la
forme d'une bibliothèque (libcrbn) qui centralise l'intégralité du
processus : lecture d'une scène depuis un fichier, écriture d'un scène
dans un fichier, stockage des données et mécanisme de génération de
l'image finale. La visualisation est faite via un programme externe.
Libcrbn utilise un ensemble de modules pour donner un sens au données.
Elle ne sait donc pas ce qu'est une quadrique ou un maillage,
l'algorithme de Whitted ou celui nommé Metropolis Light Transport ;
juste que les premiers sont des primitives géométriques et les seconds
des algorithmes d'illumination.


Après le "premature optimization is the root of all evil" on a droit une
sorte d' "over-generalization, over-abstraction, all is virtualized".
Autrement, c'est une interface mais libcrbn ne sait pas ce qu'elle
interface, le tout en Python. (au revoir les performances) Cela peut
constituer une première ébauche qui serait réécrite ensuite en C++.

Après, n'importe qui peut ajouter un greffons à blender, maya, 3dsmax,
ou softimage pour qu'il exploite libcrbn pour effectuer le rendu des
images.


Je suppose que le calcul du rendu n'est pas vraiment fait en Python

Pour ma part, J'ai un programme en ligne de commande pour lancer
l'interprètation d'un fichier de scène.


évidemment ce programme lit tout le fichier de scène dans une chaîne
gigantesque et envoie un bon eval() ou exec des familles ? Ou bien je
n'ai rien compris à l'architecture de tout le bouzin ? (1)

(c'est tellement bien écrit que j'vais mettre à jour ma page oueb;)


Bonne idée. Et mettre un message ici et sur comp.lang.python avec l'URL
serait pas mal.

Pour que libcrbn puisse lire une scène, elle intégre donc un
interpréteur (en flex/bison au début, Lua par la suite, Python à l'heure
actuelle et dans un futur proche un parser maison) auquel j'ajoute des
fonctions pour qu'il fasse appel à l'API de Crbn. L'interpréteur est
interne à libcrbn, nous ne sommes donc pas, en considérant Python comme
l'interpréteur, dans le cas de PIL ou de PyXML qui sont des extensions à
Python installées dans /usr/lib/python$VERSION/site-packages/...

Je me permet de revenir sur le choix d'un parser. Il n'est pas facile
(surtout dans le cas de gros volumes de donnée). En dehors des
limitations de chaque langage, l'utilisation mémoire est une chose
importante à considérer. En effet, si on utilise un langage (Lua,
Python, Ruby ou autre), il faut savoir que l'on a généralement des
duplications d'informations : lors de la phase de lecture, dans
l'interpréteur même et dans son propre programme.


Le principe même du "parser" c'est, il me semble, de pouvoir décoder en
jetons et même en appels de fonctions de rappel un flux qui peut être
fourni par petits bouts, je ne vois donc pas vraiment de duplication
d'informations si ce n'est la (ou les) malheureuse ligne en clair que
l'on donne au parser.

un langage qui lit/exécute un fichier pas à pas (à savoir lit une
déclaration, la compile, l'exécute puis l'oubli) permet de réduire les 2
premiers cas mais pas de les supprimer. On ne fait que repousser le
problème. Un déclaration de 100 Mo utilisera toujours 300 Mo (je
schématise;)


Décrire un triangle avec 9 coordonnées n'est donc pas une "déclaration"
? J'ai du mal à suivre la terminologie employée.

C'est pourquoi je me rabats sur un interpréteur incrémental (qui utilise
une quantité fixe et réduite de mémoire pour l'interprétation et ne fait
aucunes duplications). Dans l'absolu, c'est la meilleure solution.


La seule solution envisageable.

D'autre part, lisez la
documentation OpenGL sur « triangle strip » et « quad strip » vous
devriez pouvoir économiser le passage de coordonnées redondantes.


Vous avez été suffisamment débrouillard pour trouver la page Internet de
mon projet, lisez le donc en entier (rubrique «modules» pour vous
aiguiller) et vous comprendrez que l'objet de type «triangle» est la
seule entité actuellement implémentée pour gérer ce qui relève de
modélisation à base de triangle. Un objet de type «maillage» (avec les
optimisations qui vont biens) est juste à faire :)


Bon courage.

Ça fait une bonne dizaine d'années que mes lectures et mes programmes
tournent autours de la synthèse d'image et «seulement» depuis 5 ans pour
ce qui est du lancer de rayons. J'ose espérer que vous me faites
confiance quant à mes choix :)


Et ma suggestion d'un message sur comp.lang.python avec un exemple du
trajet suivi par un triangle de la scène ?

Note
(1) je suis architecte naval de formation et ai eu la chance de faire
mes études à une époque si reculée (début des années septante) qu'à part
FORTRAN 66 il n'y avait rien :-(

--
La démonstration hydrodynamique
http://littlejohn.75.free.fr/demo_h/index.html


Avatar
tiissa
Si j'ai bien compris ce que j'ai lu dans tout ce fil de discussion, vous
générez d'une certaine manière un script python, qui n'est en fait
qu'une collection d'objets ou de données, et vous souhaitez le lire et
l'exécuter petit à petit, c'est ça ?

Si oui, ce doit être possible avec exec, non ?
Je ne l'ai jamais utilisé et il semble qu'il y ait des problèmes si
l'instruction fait plusieurs lignes.
D'un autre côté, c'est vous qui générez votre script : si vous ne pouvez
tout faire tenir sur une ligne, il y a donc au moins moyen de le décorer.

Par exemple, vous pouvez peut-être inclure un commentaire particulier
avant les instructions multi-lignes :

#### mini.py
print 1
a=2
# comment
print a
#5
print
'%d'
%(a+1,
)
#1
#1
print sttmt

####


Rapidement on peut alors faire un mini interpréteur un peu comme ça :

#### inter.py
f=iter(open('mini.py'))
for l in f:
if l[:2]=='# ':
pass
elif l[0]=='#':
sttmt=''
for i in range(int(l[1:])):
sttmt=sttmt+f.next()
else:
sttmt=l
exec sttmt
####


L'exécution donne alors :

$ python mini.py
1
2
3
Traceback (most recent call last):
File "mini.py", line 12, in ?
print sttmt
NameError: name 'sttmt' is not defined
$ python inter.py
1
2
3
print sttmt

$


On note que l'exécution utilise l'environnement courant (d'où l'accès à
sttmt). Il faut donc faire attention à ce qu'il n'y ait pas
d'interférences entre les variables de l'interpréteur et ceux du script.

Bon, honnêtement, je ne trouve pas ça très joli.


Sinon s'il s'agit de données un script lisant ces données me parait
mieux que générer un script les contenant.
Par exemple pourquoi ne pas utiliser pickle en mettant les objets un par
un (ou avec la granularité voulue pour la lecture) dans le fichier ?

En pratique :

f=open('mini2.pkl','w')
import pickle
pickle.dump(1,f)
pickle.dump(2,f)
pickle.dump(3,f)
f.close()





Puis le script de chargement :

#### inter2.py
from pickle import load

f=open('mini2.pkl')
try:
while True:
a=load(f)
print a
except EOFError:
f.close()
####


On a alors sans surprise :

$ python inter2.py
1
2
3
$


Evidemment dans ce cas, il faut que ce soit toujours la même action sur
les objets (insertion dans un graphe de scène par exemple) ou pouvoir la
déterminer à l'aide de l'objet (mais il y a toujours moyen de décorer
l'objet pour y rajouter un 'message' pour ce faire).

S'il s'agit vraiment de données, c'est d'ailleurs plutôt ce type
d'approche que j'utiliserai plutôt qu'un script.
Je sais que vous générez votre fichier à partir de C++ mais j'ai cru
lire que pickle y était disponible. Sinon il doit y avoir moyen de
trouver un format d'échange lisible de manière incrémentale par un
script python (je ne sais pas pour xml ?) plutôt que de générer un
script monolythique.


Voilà quelques idées ; j'espère n'être pas passé à côté de la problématique.



Avatar
Christophe Cavalaria
Rémi Hérilier wrote:
Après un court moment de réflexion, on se dit que c'est parfaitement
faisable en Python. Par contre, le problème initial n'est toujours pas
résolu. Pour rappel, c'est les difficultés de Python à manipuler de gros
scripts et à fortiori de grosses déclarations. En effet, un maillage
conséquent (plusieurs dizaine de milliers de faces) représente, en
ASCII, plusieurs Mo. Je me retrouverai donc dans le même cas que
demander à Python de me digérer un fichier de 15 Mo.


Et en fait, il n'y a probablement aucun langage utilisable. Il faut bien
dire que pour les maillages de grande taille, même OpenGL abandonne la
modelisation par vertex(x,y,z); vertex(x,y,z); ... et remplace ça par des
vertexbuffer. Il vaudrait mieux faire pareil dans ton script et accepter
l'idée d'avoir plusieurs fichier binaires contenant les maillages et
textures à coté de ton script ( les textures ne sont pas faites inline au
script j'espère ? :) )

En fait, le pricinpale problème de cette solution c'est qu'elle scale très
mal. Inevitablement, les utilisateurs vont vouloir manipuler des données de
plus en plus complexes et donc il est très important de fournir les
meilleures performances possibles pour charger un maillage ou un ensemble
de triangles en mémoire.

1 2 3