Search code examples
pythonkerasmodelpyinstallerexe

Pyinstaller created exe has an AttributeError


I have created an exe file with pyinstaller with the following command:

pyinstaller --name BrewTwin --onefile --add-data "models;models" --add-data "needed_data;needed_data" --add-data "icons;icons" --windowed --icon=icons/brewTwin_logo.ico brewTwin_brand_new.py

During the creating no failures were logged but when I want to start the program via the exe file I get an AttributeError: 'NoneType' object has no attribute 'write' which I do not get when I run the programm in my IDE. This error happens in the following line of code:

self.firstoutput = self.model.predict(tf.convert_to_tensor(self.firstpredict, dtype=tf.float32))

Some information about my program: I have written an class for an GUI with tkinter in python 3.9 were the line of code is in the init method of my class. The model I load is a Keras LSTM Network which I load with keras.models.load_model(resource_path(model_path), compile=False)

The whole error message is:

Traceback (most recent call last):
  File "brewTwin_brand_new.py", line 1117, in <module>
  File "brewTwin_brand_new.py", line 50, in __init__
  File "keras\src\utils\traceback_utils.py", line 70, in error_handler
  File "keras\src\utils\traceback_utils.py", line 65, in error_handler
  File "keras\src\engine\training.py", line 2575, in predict
  File "keras\src\callbacks.py", line 519, in on_predict_batch_end
  File "keras\src\callbacks.py", line 322, in _call_batch_hook
  File "keras\src\callbacks.py", line 345, in _call_batch_end_hook
  File "keras\src\callbacks.py", line 393, in _call_batch_hook_helper
  File "keras\src\callbacks.py", line 1101, in on_predict_batch_end
  File "keras\src\callbacks.py", line 1170, in _batch_update_progbar
  File "keras\src\utils\generic_utils.py", line 296, in update
  File "keras\src\utils\io_utils.py", line 79, in print_msg
AttributeError: 'NoneType' object has no attribute 'write'

If there were any further information needed let me know.


Solution

  • For anyone else who might have the same or a similar problem: I found a solution myself in the meantime.

    I just need to suppress the console output of the tensorflow and keras module by adding the following lines of code:

    import sys
    import os
    import tensorflow as tf
    import keras.models import load_model
    
    if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
        # Change the standard output
        sys.stdout = open(os.devnull, 'w')
        sys.stderr = open(os.devnull, 'w')
        os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
        tf.get_logger().setLevel('ERROR')
        logging.getLogger('tensorflow').setLevel(logging.ERROR)
    

    With the if statement, I make sure that I have my standard output in the console when developing.