Seite 1 von 1

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

Verfasst: Donnerstag 3. Januar 2019, 21:44
von darktrym
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.

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

Verfasst: Donnerstag 3. Januar 2019, 22:00
von sparrow
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

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

Verfasst: Donnerstag 3. Januar 2019, 22:18
von Sirius3

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

Verfasst: Freitag 4. Januar 2019, 09:39
von darktrym

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']

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

Verfasst: Freitag 4. Januar 2019, 10:25
von Sirius3
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.

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

Verfasst: Freitag 4. Januar 2019, 11:42
von __blackjack__
@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.