kquick / Thespian

Python Actor concurrency library
MIT License
189 stars 24 forks source link

Failure to start any multiproc base when using pyinstaller #46

Closed jwelch1324 closed 5 years ago

jwelch1324 commented 5 years ago

When running my program using the standard python command

python Collector.py

Everything runs smoothly, and I get the expected output

>python Collector.py
Loading Application.py 
Loading Application.py
Loading Application.py
Loading Application.py
Loading Application.py
Loading Application.py
Setting up VK Tables
Attemping to load hkm_data.npy
hkm_data.npy loaded

Each of the 'Loading Application.py' is just to tell me when each process is loading the file.

For reference here is the source for collector.py that launches the actorsystem.

import sys
import Actors
from Application import KSApplication
from thespian.actors import ActorSystem
from thespian.system import multiprocTCPBase
import keyboard
# Create the application and start running in the background.

if __name__ == "__main__":
    asys = ActorSystem('multiprocTCPBase')
    #asys = ActorSystem('multiprocQueueBase')
    app = KSApplication()
    app.add_actor("TGHTActor")
    app.run()
    asys.shutdown()

However, if I now build a standalone application with pyinstaller using just the basic command

pyinstaller Collector.py

The build proceeds as normal, but when I run the application I get the following exception

Loading Application.py 
Loading Application.py
Loading Application.py
Loading Application.py
Loading Application.py
Traceback (most recent call last):
  File "Collector.py", line 12, in <module>
  File "site-packages\thespian\actors.py", line 638, in __init__
  File "site-packages\thespian\actors.py", line 676, in _startupActorSys
  File "site-packages\thespian\system\multiprocTCPBase.py", line 28, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 86, in __init__
  File "site-packages\thespian\system\systemBase.py", line 329, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 115, in _startAdmin
thespian.actors.InvalidActorAddress: ActorAddr-(T|:1900) is not a valid ActorSystem admin
[3396] Failed to execute script Collector
Loading Application.py
Traceback (most recent call last):
  File "Collector.py", line 12, in <module>
  File "site-packages\thespian\actors.py", line 638, in __init__
  File "site-packages\thespian\actors.py", line 676, in _startupActorSys
  File "site-packages\thespian\system\multiprocTCPBase.py", line 28, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 86, in __init__
  File "site-packages\thespian\system\systemBase.py", line 329, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 115, in _startAdmin
thespian.actors.InvalidActorAddress: ActorAddr-(T|:1900) is not a valid ActorSystem admin
[856] Failed to execute script Collector
Loading Application.py
Traceback (most recent call last):
  File "Collector.py", line 12, in <module>
  File "site-packages\thespian\actors.py", line 638, in __init__
  File "site-packages\thespian\actors.py", line 676, in _startupActorSys
  File "site-packages\thespian\system\multiprocTCPBase.py", line 28, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 86, in __init__
  File "site-packages\thespian\system\systemBase.py", line 329, in __init__
  File "site-packages\thespian\system\multiprocCommon.py", line 115, in _startAdmin
thespian.actors.InvalidActorAddress: ActorAddr-(T|:1900) is not a valid ActorSystem admin
[13668] Failed to execute script Collector

And this continues over and over until I force quit the process

If instead of using multiprocTCPBase, I use the simpleSystemBase, everything runs as expected.

I have tried the suggestions that I could find such as killing all python processes and restarting machine to clear any potentially hung admin processes. However the fact that it works when I run it from the command line suggests it is something happening in the pyinstaller process... a missing dependency perhaps?

jwelch1324 commented 5 years ago

Problem was indeed a missing thespian module dependency (though which one exactly I am not sure)

The solution is to create a hook file for the thespian library as follows

# hook-thespian.py
# Adds hidden imports to support thespian in the pyinstaller build
from PyInstaller.utils.hooks import collect_submodules

hiddenimports = []

for mod in collect_submodules('thespian'):
    if not mod.startswith('thespian.test'):
        hiddenimports.append(mod)

Then somewhere in the toplevel application file include the line

import thespian

Then running pyinstaller with the command line

>pyinstaller --additional-hooks-dir=hooks Application.py

where hooks is the directory containing hook-thespian.py will produce an standalone executable that runs as expected.

Works with all the multiproc bases.