0

I have a complicated code and therefore I'm going to demonstrate my issue with the program of somebody else, who created a calculator for the digits of PI.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
ZetCode Tkinter e-book

This script produces a long-running task of calculating 
a large Pi number, while keeping the GUI responsive.
This is an example written for Windows.

Author: Jan Bodnar
Last modified: January 2016
Website: www.zetcode.com
"""

from tkinter import (Tk, BOTH, Text, E, W, S, N, END, 
    NORMAL, DISABLED, StringVar)
from tkinter.ttk import Frame, Label, Button, Progressbar, Entry
from tkinter import scrolledtext

from multiprocessing import Process, Manager, Queue
from queue import Empty
from decimal import Decimal, getcontext


DELAY1 = 80
DELAY2 = 20

# Queue must be global
q = Queue()

class Example(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent, name="frame")   

        self.parent = parent
        self.initUI()


    def initUI(self):

        self.parent.title("Pi computation")
        self.pack(fill=BOTH, expand=True)

        self.grid_columnconfigure(4, weight=1)
        self.grid_rowconfigure(3, weight=1)

        lbl1 = Label(self, text="Digits:")
        lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10)

        self.ent1 = Entry(self, width=10)
        self.ent1.insert(END, "4000")
        self.ent1.grid(row=0, column=1, sticky=W)

        lbl2 = Label(self, text="Accuracy:")
        lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10)

        self.ent2 = Entry(self, width=10)
        self.ent2.insert(END, "100")
        self.ent2.grid(row=0, column=3, sticky=W)        

        self.startBtn = Button(self, text="Start", 
            command=self.onStart)
        self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W)

        self.pbar = Progressbar(self, mode='indeterminate')        
        self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E)     

        self.txt = scrolledtext.ScrolledText(self)  
        self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5,
            columnspan=5, sticky=E+W+S+N)


    def onStart(self):

        self.startBtn.config(state=DISABLED)
        self.txt.delete("1.0", END)

        digits = int(self.ent1.get())
        accuracy = int(self.ent2.get())

        self.p1 = Process(target=generatePi, args=(q, digits, accuracy))
        self.p1.start()
        self.pbar.start(DELAY2)
        self.after(DELAY1, self.onGetValue)


    def onGetValue(self):

        if (self.p1.is_alive()):

            self.after(DELAY1, self.onGetValue)
            return
        else:    

           try:

                self.txt.insert('end', q.get(0))
                self.txt.insert('end', "\n")
                self.pbar.stop()
                self.startBtn.config(state=NORMAL)

           except Empty:
                print("queue is empty")

# Generate function must be a top-level module funtion            
def generatePi(q, digs, acc):

    getcontext().prec = digs

    pi = Decimal(0)
    k = 0
    n = acc

    while k < n:
        pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \
            (Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \
            (Decimal(1)/(8*k+6)))
        k += 1

    q.put(pi)


def main():  

    root = Tk()
    root.geometry("400x350+300+300")
    app = Example(root)
    root.mainloop()  


if __name__ == '__main__':
    main()  

The problem is I want to make an executable of my program and I do this with cx_Freeze. The program if you run it with the command line, it works totally fine. But then I tried to make an Executable and what happens, whenever you start the multiprocess: Instead of getting your function done. It runs the whole program a second time so instead having your function being done you end up having two windows with no function done.

It may be useful to see how I created the executable:

import sys
import setuptools
from cx_Freeze import setup, Executable

# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
    base = "Console"

setup(  name = "Test",
        version = "1.0.0",
        description = "Test",
        options = {
            "build_exe": {
                "packages": ["tkinter","multiprocessing","queue","decimal"],
                'includes': ['test'],
                'include_msvcr': True
            },
        },
        executables = [Executable("test.py", base=base,icon = "rsc/imgs/BlackIcon.ico")]
        )

I have been using easy functions like print("Hello World"), but also more complicated ones, none of them have been working so I assume that this problem is caused by the combination of cx_Freeze and multiprocessing and tkinter.

So how do I create an executable with being able to start a multiprocess with the function being run as wanted?

EDIT:

As mentioned in the comments I have been adding the statement freeze_support() straight after if name == "main":

In general you are getting Errors, when you are using multiprocessing with tkinter because of pickling.(Also tried this one just in case, but no success) Therefore I use pathos, which uses dill, but when I omit the freeze_support() I get the unwanted window and if I add it, I get this TypeError.

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\cx_Freeze\initscripts\__startup__.py", line 40, in run
    module.run()
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\cx_Freeze\initscripts\Console.py", line 23, in run
    exec(code, {'__name__': '__main__'})
  File "test.py", line 134, in <module>
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\context.py", line 149, in freeze_support
    freeze_support()
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\spawn.py", line 74, in freeze_support
    spawn_main(**kwds)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\spawn.py", line 105, in spawn_main
    exitcode = _main(fd)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\spawn.py", line 115, in _main
    self = reduction.pickle.load(from_parent)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 270, in load
    return Unpickler(file, ignore=ignore, **kwds).load()
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 472, in load
    obj = StockUnpickler.load(self)
EOFError: Ran out of input
Traceback (most recent call last):
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "test.py", line 84, in onStart
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\process.py", line 112, in start
    self._popen = self._Popen(self)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\context.py", line 322, in _Popen
    return Popen(process_obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\popen_spawn_win32.py", line 89, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\multiprocess\reduction.py", line 63, in dump
    ForkingPickler(file, protocol, *args, **kwds).dump(obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 445, in dump
    StockPickler.dump(self, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 437, in dump
    self.save(obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 549, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 662, in save_reduce
    save(state)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 1413, in save_function
    obj.__dict__, fkwdefaults), obj=obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 638, in save_reduce
    save(args)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 789, in save_tuple
    save(element)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 1295, in save_module
    state=_main_dict)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 662, in save_reduce
    save(state)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 1295, in save_module
    state=_main_dict)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 662, in save_reduce
    save(state)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 1295, in save_module
    state=_main_dict)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 662, in save_reduce
    save(state)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 549, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 662, in save_reduce
    save(state)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 504, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\site-packages\dill\_dill.py", line 912, in save_module_dict
    StockPickler.save_dict(pickler, obj)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 859, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 885, in _batch_setitems
    save(v)
  File "C:\Users\semjo\AppData\Local\Programs\Python\Python37\lib\pickle.py", line 524, in save
    rv = reduce(self.proto)
TypeError: can't pickle zipimport.zipimporter objects
Sem_jong
  • 41
  • 12
  • Does this answer your question? [PyInstaller-built Windows EXE fails with multiprocessing](https://stackoverflow.com/questions/24944558/pyinstaller-built-windows-exe-fails-with-multiprocessing) – stovfl Dec 03 '19 at 16:43
  • Unfortunately not, so I havent been figuring out, how to solve it with cx_Freeze and therefor I created the Exe now with pyinstaller and I do not have any issues with the combination of multiprocessing and the freeze. Nevertheless I would have loved to do it with cx_Freeze... If you want to, you can still recreate the issue by also creating an exe and than you will know what I mean by unwanted window. – Sem_jong Dec 05 '19 at 07:51
  • Does this answer your question? [why-does-pythons-multiprocessing-module-import-main-when-starting-a-new-pro](https://stackoverflow.com/questions/14175348/why-does-pythons-multiprocessing-module-import-main-when-starting-a-new-pro) or [multiprocessing-freeze-support](https://stackoverflow.com/questions/13922597/multiprocessing-freeze-support) – stovfl Dec 05 '19 at 08:32
  • I think it's right that I have to add the cx_Freeze() method I have been doing that, but I cant get it fixed, because I get a new error. I will edit my quesion – Sem_jong Dec 05 '19 at 11:27
  • You are going to mix things up. Your question ***"...unwanted window"*** is answered. Open a new question about your ***"new error"***- – stovfl Dec 05 '19 at 12:05

0 Answers0