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