Question

J'ai récemment besoin d'écrire un script qui effectue une se scinder en deux processus os.fork () . Le processus enfant devient un processus serveur et transmet les données au processus parent à l'aide d'un tuyau réalisé avec os.pipe () . L'enfant ferme la 'r' extrémité du tuyau et le parent ferme la 'w' extrémité du tuyau, comme d'habitude. Je convertir les retours du tuyau () en objets de fichiers avec os.fdopen .

Le problème que je vais avoir est la suivante: Le processus fourchettes avec succès, et l'enfant devient un serveur. Tout fonctionne très bien et l'enfant écrit docilement les données à l'ouverture fin du read() tuyau. Malheureusement, la fin de base de la conduite fait deux choses étranges:
A) Il bloque sur le fonctionnement de <=> sur la <=> extrémité du tuyau.
En second lieu, il ne parvient pas à lire toutes les données qui ont été mis sur la conduite à moins que la fin est entièrement <=> fermée.

J'ai immédiatement pensé que tampon était le problème et a ajouté pipe.flush () appels, mais ceux-ci n'a pas aidé.

Quelqu'un peut-il faire la lumière sur pourquoi les données ne semble pas jusqu'à la fin de l'écriture est complètement fermée? Et est-il une stratégie pour faire le blocage appel non <=>?

Ceci est mon premier programme Python qui fourchus ou tuyaux utilisés, alors pardonnez-moi si je l'ai fait une simple erreur.

Était-ce utile?

La solution

Utilisez-vous lecture () sans spécifier la taille ou le traitement de la conduite comme un iterator (for line in f)? Si oui, c'est probablement la source de votre problème - est défini lire () pour lire jusqu'à la fin du fichier avant de revenir, plutôt que de lire tout ce qui est disponible pour la lecture. Cela signifiera qu'il va bloquer jusqu'à ce que l'enfant appelle close ().

Dans le code exemple lié à, c'est OK - le parent agit d'une manière de blocage, et en utilisant simplement l'enfant à des fins d'isolement. Si vous voulez continuer, alors soit utiliser IO non bloquante comme dans le code affiché (mais soyez prêt à traiter les données demi-complet), ou lire en morceaux (par exemple r.read (taille) ou r.readline () ) qui bloque uniquement jusqu'à ce qu'une taille spécifique / ligne a été lu. (Vous aurez toujours besoin d'appeler flush sur l'enfant)

On dirait que le traitement de la conduite comme un itérateur utilise une autre tampon aussi bien, pour « for line in r: » ne peut pas vous donner ce que vous voulez si vous avez besoin chaque ligne pour être immédiatement consommée. Il peut être possible de désactiver, mais simplement en spécifiant 0 pour la taille de la mémoire tampon dans fdopen ne semble pas suffisante.

Heres quelques exemples de code qui devrait fonctionner:

import os, sys, time

r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)

pid = os.fork()
if pid:          # Parent
    w.close()
    while 1:
        data=r.readline()
        if not data: break
        print "parent read: " + data.strip()
else:           # Child
    r.close()
    for i in range(10):
        print >>w, "line %s" % i
        w.flush()
        time.sleep(1)

Autres conseils

Utilisation

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

Avant d'appeler la lecture () résout les deux problèmes. La lecture () appel ne bloque plus et les données apparaît après seulement une quinte () à la fin de l'écriture.

Je vois que vous avez résolu le problème de blocage i / o et mise en mémoire tampon.

Une note si vous décidez d'essayer une approche différente: subprocess est l'équivalent / remplacement de l'idiome fork / exec. Il semble que ce n'est pas ce que vous faites: vous avez juste une fourchette (pas un exec) et l'échange de données entre les deux processus - dans ce cas, le multiprocessing module (en Python 2.6+) serait un meilleur ajustement.

La partie de la fourchette « parent » par rapport à « enfant » dans une application Python est stupide. Il est un héritage de jours unix 16 bits. Il est un d'une afféterie jour où fork / exec et exec étaient choses importantes à tirer le meilleur parti d'un tout petit processeur.

Cassez votre code Python en deux parties distinctes:. Parent et enfant

La partie parent doit utiliser subprocess pour exécuter la partie de l'enfant.

Une fourchette et exec peut se produire quelque part là-dedans - mais vous n'avez pas besoin de soins

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top