Question

Je travaille sur une application graphique qui a besoin pour gérer les processus externes. Travailler avec des processus externes conduit à beaucoup de problèmes qui peuvent rendre la vie d'un programmeur difficile. Je me sens comme maintenence sur cette application prend un temps trop longue. J'ai essayé d'énumérer les choses qui rendent le travail avec des processus externes si difficile que je puisse trouver des moyens d'atténuer la douleur. Ce genre de transformé en une diatribe que je pensais que je poste ici afin d'obtenir des commentaires et de fournir des conseils à tous ceux qui envisagent de la voile dans ces eaux très troubles. Voici ce que j'ai à ce jour:

  1. La sortie de l'enfant peut se mélanger avec la sortie du parent. Cela peut rendre les sorties trompeuses et difficiles à lire. Il peut être difficile de dire ce qui est venu d'où. Il devient plus difficile de comprendre ce qui se passe quand les choses sont asynchrones. Voici un exemple artificiel:

    import textwrap, os, time
    from subprocess import Popen
    test_path = 'test_file.py'
    
    with open(test_path, 'w') as file:
        file.write(textwrap.dedent('''
            import time
            for i in range(3):
                print 'Hello %i' % i
                time.sleep(1)'''))
    
    proc = Popen('python -B "%s"' % test_path)
    
    for i in range(3):
        print 'Hello %i' % i
        time.sleep(1)
    
    os.remove(test_path)
    

    Sortie:

    Hello 0
    Hello 0
    Hello 1
    Hello 1
    Hello 2
    Hello 2
    

    Je suppose que je pourrais avoir le processus d'enfant à écrire sa sortie vers un fichier. Mais il peut être ennuyeux d'avoir à ouvrir un fichier à chaque fois que je veux voir le résultat d'une instruction d'impression.

    Si j'ai le code pour le processus d'enfant que je pourrais ajouter une étiquette, quelque chose comme print 'child: Hello %i', mais il peut être gênant de le faire pour chaque impression. Et il ajoute un peu de bruit à la sortie. Et bien sûr, je ne peux pas le faire si je n'ai pas accès au code.

    je pouvais gérer manuellement la sortie du processus. Mais alors vous ouvrez une boîte de Pandore avec des fils et des sondages et des trucs comme ça.

    Une solution simple consiste à traiter les processus comme fonctions synchrones, qui est, aucune autre exécute de code jusqu'à ce que le processus de finalise. En d'autres termes, faire le bloc de processus. Mais cela ne fonctionne pas si vous construisez une application IUG. Ce qui me amène au problème suivant ...

  2. Blocage des processus cause de l'interface graphique utilisateur ne répond plus.

    import textwrap, sys, os
    from subprocess import Popen
    
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    test_path = 'test_file.py'
    with open(test_path, 'w') as file:
        file.write(textwrap.dedent('''
            import time
            for i in range(3):
                print 'Hello %i' % i
                time.sleep(1)'''))
    
    app = QApplication(sys.argv)
    button = QPushButton('Launch process')
    def launch_proc():
        # Can't move the window until process completes
        proc = Popen('python -B "%s"' % test_path)
        proc.communicate()
    button.connect(button, SIGNAL('clicked()'), launch_proc)
    button.show()
    app.exec_() 
    os.remove(test_path)
    

    Qt fournit une enveloppe de processus de son propre appelé QProcess qui peut aider. Vous pouvez connecter des fonctions aux signaux de sortie de capture relativement facilement. Voilà ce que je suis en train d'utiliser. Mais je trouve que tous ces signaux se comportent étrangement comme des déclarations de goto et peuvent conduire à un code spaghetti. Je pense que je veux tri du comportement de blocage en ayant le signal « fini » de QProcess appeler une fonction contenant tout le code qui vient après l'appel de processus. Je pense que cela devrait fonctionner, mais je suis encore un peu flou sur les détails ...

  3. traces de pile s'interrompu quand vous allez dans le processus de retour à l'enfant du processus parent. Si une vis de la fonction normale, vous obtenez une belle trace complète de la pile avec des noms et des numéros de ligne. Si une vis de sous-processus, vous serez chanceux si vous obtenez une sortie du tout. Vous finissez par avoir à faire beaucoup plus travail de détective à chaque fois que quelque chose va mal.

  4. En parlant de sortie a une façon de disparaître lorsque le traitement des processus externes. Comme si vous exécutez quelque chose via les fenêtres commande de cmd ', la console affiche, exécutez le code, puis disparaissent avant d'avoir une chance de voir la sortie. Vous devez passer le drapeau / k pour le faire coller autour. Des problèmes similaires semblent surgir tout le temps.

    Je suppose que les deux problèmes 3 et 4 ont la même cause: aucune manipulation d'exception. La gestion des exceptions est destiné à être utilisé avec des fonctions, il ne fonctionne pas avec les processus. Peut-être il y a un moyen d'obtenir quelque chose comme la gestion des exceptions pour les processus? Je suppose que ce stderr est pour? Mais face à deux courants différents peut être gênant en soi. Peut-être que je devrais regarder dans ce plus ...

  5. Les processus peuvent accrocher et rester en arrière-plan sans vous en rendre compte. Donc, vous finissez par crier à votre ordinateur cuz il va si lent jusqu'à ce que vous enfin mettre votre gestionnaire de tâches et voir 30 instances du même processus traîner dans le backgrounré.

    En outre, la pendaison des processus d'arrière-plan peut interefere avec d'autres instances du processus de diverses manières amusantes, comme causant des erreurs d'autorisations en maintenant une poignée dans un fichier ou someting comme ça.

    Il semble comme une solution facile à ce serait d'avoir le processus parent tuer le processus de l'enfant à la sortie si le processus de l'enfant n'a pas fermé lui-même. Mais si le parent processus se bloque, le code de nettoyage pourrait ne pas obtenir appelé et l'enfant peut être laissée en suspens.

    En outre, si les attentes des parents pour l'enfant à remplir, et l'enfant est dans une boucle infinie ou quelque chose, vous pouvez vous retrouver avec deux processus de suspension.

    Ce problème peut lier pour problème 2 pour le plaisir supplémentaire, ce qui provoque votre IUG cesser de répondre entièrement et vous forcer à tuer tout avec le gestionnaire de tâches.

  6. F *** ing citations

    Paramètres souvent doivent être transmis aux processus. Ceci est un casse-tête en soi. Surtout si vous traitez avec des chemins de fichiers. Dis ... 'C: / Mes Documents / whatever /. Si vous ne disposez pas de guillemets, la chaîne sera souvent divisée à l'espace et interprété comme deux arguments. Si vous avez besoin des citations imbriquées vous pouvez utiliser « et « Mais si vous avez besoin d'utiliser plus de deux couches de citations, vous devez faire un peu Escaping méchant, par exemple:. » Cmd / k « python \ » chemin 1 \ » \ » voie 2 \ '' ».

    Une bonne solution à ce problème passe des paramètres comme une liste plutôt que comme une seule chaîne. Subprocess vous permet de le faire.

  7. Impossible de retourner facilement les données d'un sous-processus.

    Vous pouvez utiliser stdout bien sûr. Mais si vous voulez lancer une impression là-dedans pour des fins de débogage? C'est va bousiller le parent si elle est formatée attendant la sortie d'une certaine façon. Dans les fonctions que vous pouvez imprimer une chaîne et retourner une autre et tout fonctionne très bien.

  8. drapeaux de ligne de commande et Obscure un système d'aide basé sur un terminal merdique.

    Ce sont des problèmes que je souvent INTRODUISE lors de l'utilisation des applications de niveau d'os. Comme le drapeau / k je l'ai mentionné, pour la tenue d'une fenêtre cmd ouverte, qui a eu l'idée que? des applications Unix ne tendent pas à être beaucoup plus favorable à cet égard. Espérons que vous pouvez utiliser Google ou StackOverflow pour trouver la réponse dont vous avez besoin. Mais sinon, vous avez beaucoup de lecture ennuyeux et le procès frusterating et erreur de le faire.

  9. Les facteurs externes.

    Celui-ci est le genre de flou. Mais lorsque vous quittez le port relativement à l'abri de vos propres scripts pour traiter les processus externes vous vous trouvez avoir à traiter avec le « monde extérieur » dans une mesure beaucoup de plus. Et c'est un endroit effrayant. Toutes sortes de choses peuvent mal tourner. Juste pour donner un exemple au hasard:. Rtc dans lequel un processus est exécuté peut modifier le comportement de ce

Il y a probablement d'autres questions, mais ce sont ceux que j'ai écrit jusqu'à présent. Tout autre accrocs que vous souhaitez ajouter? Toutes les suggestions pour faire face à ces problèmes?

Était-ce utile?

La solution

Consultez le module de sous-processus. Il devrait aider à la séparation de sortie. Je ne vois pas autour soit des flux de sortie séparés ou une sorte de marquage de sortie dans un seul flux.

Le problème du processus de suspension est difficile aussi bien. La seule solution que je suis en mesure de faire est de mettre une minuterie sur le processus externe, et tuez-le si elle ne retourne pas dans le temps imparti. Brut, méchant, et si quelqu'un d'autre a une bonne solution, j'aimerais l'entendre pour que je puisse l'utiliser aussi.

Une chose que vous pouvez faire pour aider à faire face au problème de l'arrêt complètement non gérés est de garder un répertoire de fichiers pid. Chaque fois que vous le coup d'envoi d'un processus externe, écrire un fichier dans votre répertoire de fichiers pid avec un nom qui est le pid du processus. Effacer le fichier pid quand vous savez que le processus est sorti proprement. Vous pouvez utiliser la substance dans le répertoire pid pour aider le nettoyage sur les accidents ou redémarrages.

Cela ne peut fournir des réponses satisfaisantes ou utiles, mais peut-être c'est un début.

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