Newsgroup: it.comp.os.linux.development
Titolo: python & pipes

salve a tutti,
devo scrivere velocemente un'interfaccia grafica per un programmino
a linea di comando e, non avendo tempo ne' voglia di scrivere un
programma in c, mi sono lanciato sul python+gtk. Fare l'interfaccia
vera e propria e' banale anche per me che non ho mai usato il python,
basta conoscere un po' le gtk, ma ho un problema con la comunicazione
tra i due processi.
Io apro due pipe con popen2, tuttavia, nonostante il processo ad una
estremita' scriva dati come un forsennato, allo script python
arrivano "a blocchi", ovvero per un po' non legge niente, poi ne
legge una valanga in blocco, poi si ferma di nuovo e cosi' via.
Evidentemente c'e' qualche buffer di mezzo che mi rompe le scatole,
ho provato ad azzerare la dimensione del buffer con popen2(..., 0) ma
non cambia nulla. Colpa del buffer della pipe stessa a livello di
sistema operativo? E, soprattutto, come si puo' risolvere questo
problema? Io devo assolutamente elaborare i dati man mano che il
programma li sputa fuori.
Un altro problema secondario e' che readline(), su un file descriptor
non bloccante non e' detto che legga effettivamente un'intera linea,
ma a questo spero di porre rimedio in un modo o nell'altro una volta
risolto il primo punto.
Allego lo script python (abbiate pieta' di me, e' la prima cosa che
scrivo con questo linguaggio ;)) e un programmino in C per fare il
test. Grazie a chiunque mi dia una dritta :)
----- pippo.c ----------------------------
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void){
int flag=1, count=0, strflags;
char c;
	strflags = fcntl(0, F_GETFL);
	strflags |= O_NONBLOCK;
	fcntl(0, F_SETFL, strflags);
	while(1){
		usleep(1000);
		if(read(0, &c, 1) != -1)
			if(c == 's')
				flag = -flag;
		if(flag==1)
			count++;
		else
			count--;
 
		printf("%d\n",count);
	}
	return 0;
}
------------------------------------------
----- test.py ----------------------------
#!/usr/bin/env python
from gtk import *
from popen2 import popen2
from fcntl import *
from os import O_NONBLOCK
def switch(*args):
	input.write("s\n")
	print "write fatto"
def read_func(*args):
	ris = output.readline()
	if ris != "":
		label.set_text(ris)
	print "read fatto"
	return TRUE
def destroy(*args):
	window.hide()
	mainquit()
output, input = popen2('a.out')
fcntl(output, F_SETFL, O_NONBLOCK)
window = GtkWindow(WINDOW_TOPLEVEL)
window.connect("destroy", destroy)
box1 = GtkVBox()
window.add(box1)
box1.show()
button = GtkButton("switch")
button.connect("clicked", switch)
box1.pack_start(button)
button.show()
label = GtkLabel("")
label.show()
box1.pack_start(label)
idle_add(read_func)
window.show()
mainloop()
------------------------------------------
-- 
There are only 10 kinds of people in the world --
Those who understand binary, and those who don't.

 programma li sputa fuori.
Se sotto Python si può fare una chiamata a gdk_input_add (o
equivalente), questa è la tua risposta.
Ciao,
 Emmanuele.
-- 
Emmanuele Bassi (Zefram)           [ 
http://www.radiance.d2g.com/~zefram
 ]
GnuPG Key fingerprint = 4DD0 C90D 4070 F071 5738  08BD 8ECC DB8F A432 0FF4

 legge una valanga in blocco, poi si ferma di nuovo e cosi' via.
[...]
mi rispondo da solo: sono un pirla. Il fatto che da console il
programmino in C sembrasse scrivere i dati correttamente mi aveva
ingannato... evidentemente il buffering usato per scrivere su console
e' diverso da quello usato per scrivere in una pipe. Un bel 
setbuf(stdout, NULL)  all'inizio del programma e tutto si e' risolto.
