Pool.map, Sys.Argv, PyInstaller und nun zusätzliche Argumente in der Liste

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Ich kann leider den Code erst morgen posten, aber vielleicht kennt jemand den Grund für folgendes Verhalten.
Ziel war es Diagnosen parallel nach einem Suchwort durchsuchen zu lassen, die Delphi-Kommandozeilen-Lösung ist etwas langsam, schlecht lesbar, sequentiell mit einigen Overhead, braucht ca. 67s, macht aber auch mehr.
Also habe ich recht schnell mit ein paar Zeilen eine Python-Lösung mit Multiprocessing zusammengebastelt, ich komme nun unter 5s raus(paralleles auslesen).
Da bei uns keiner außer meine Wenigkeit Python nutzt, wollte ich eine EXE erstellen, geht recht einfach mit PyInstaller, dachte ich.
Nun hat er mir zusätzliche Argumente in sys.argv angezeigt und so meine Programm torpediert, irgendwas mit process_id, ich muss wohl die Stelle in der Doku zu PyInstaller wohl überlesen haben, die das Verhalten erklärt.
Jetzt habe ich den Code umgebaut, nutze nun Pool.starmap, aber irgendwie hätte ich doch gern den Grund hierfür erfahren.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Mach mal ein kleines Beispiel an Code, das nicht tut.
Ansonste gibt es hier ja die speziellen Sachen, die man beachten muss: https://pyinstaller.readthedocs.io/en/v ... sys-argv-0
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Code: Alles auswählen

#!/usr/bin/env python
#coding: utf-8

# for Python 3 with Pyinstaller Support

from sys import argv
from glob import glob
import multiprocessing 

search_pattern = argv[1] if len(argv)  > 1 else "*.txt"
search_word = argv[2] if len(argv)  > 2 else "Imogdaniel"

print(argv)

INSTANCE_NUMBER = 8

def worker(filename):
    result = []
    result.append("search  '%s' in '%s'\r\n" % (search_word, filename))
    for line in open(filename, "r"):
        if search_word in line:
            result.append(line)
    for line in result:
        print(line.rstrip())

if __name__ == '__main__':
    multiprocessing.freeze_support()
    pool = multiprocessing.Pool(INSTANCE_NUMBER)
    pool.map(worker, glob(search_pattern))
C:\Projekte\Sonstige\prep\dist>prep_old C:\Users\dedols\Desktop\tsdlk\Diagnose\*.txt TransportAnPAE.MakeTA
['prep_old', 'C:\\Users\\dedols\\Desktop\\tsdlk\\Diagnose\\*.txt', 'TransportAnPAE.MakeTA']
['C:\\Projekte\\Sonstige\\prep\\dist\\prep_old.exe', '--multiprocessing-fork', 'parent_pid=11280', 'pipe_handle=672']
['C:\\Projekte\\Sonstige\\prep\\dist\\prep_old.exe', '--multiprocessing-fork', 'parent_pid=11280', 'pipe_handle=680']
['C:\\Projekte\\Sonstige\\prep\\dist\\prep_old.exe', '--multiprocessing-fork', 'parent_pid=11280', 'pipe_handle=588']
['C:\\Projekte\\Sonstige\\prep\\dist\\prep_old.exe', '--multiprocessing-fork', 'parent_pid=11280', 'pipe_handle=696']
['C:\\Projekte\\Sonstige\\prep\\dist\\prep_old.exe', '--multiprocessing-fork', 'parent_pid=11280', 'pipe_handle=644']
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Bei Multiprocessing wird das Programm mit anderen Parametern aufgerufen, das ist ganz normal. search_pattern und search_word darf deshalb auch nicht auf Modulebene, sondern in einer Funktion namens `main` definiert werden, wo auch `pool` hineingehört. `worker` darf nicht auf globale Variablen zugreifen, wie das bei jeder normalen Funktion auch der Fall ist, hier aber dann zu Fehlern führt. `search_word` muß also als Argument an `worker` übergeben werden, mit functools.partial.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@darktrym: Das ist ja auch nicht wirklich PyInstaller-spezifisch, sondern generell ein „freeze“-Ding. Diese Informationen müssen halt irgendwie übertragen werden. Ohne ”gefrorenes” Programm piped `multiprocessing` einfach an den Kindprozess, denn das ist ja direkt der Python-Prozess der die Teilarbeit leistet. Mit einem ”gefrorenem” Programm ist der Kindprozess ja der, der zum Beispiel erst einmal die ”eigenständige” EXE in ein temporäres Verzeichnis entpackt und dann erst von dort aus das Python-Programm startet.

Man darf halt wenn ``--multiprocessing-fork`` in den Argumenten vorkommt, die Argumente nicht verarbeiten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten