Dan
Dan

Reputation: 33

Why a file is empty after writing to it?

I got a tkinter app and a thread which writes some data to a file. If I let the thread finish it's job, the file is empty. If I terminate the program before the thread is done (clicking the red square in pyCharm) the file is filled with the data till the point of termination. Here is a code to reproduce the problem:

import tkinter as tk
import _thread
import numpy as np

img_list = []


def create_img_list():
    for i in range(1000):
        img = np.random.rand(385, 480)
        img = img * 65535
        img = np.uint16(img)
        img_list.append(img)


def write_to_file():
    f = open("test.Raw", "wb")
    for img in img_list:
        f.write(img)
    f.close()


root = tk.Tk()
button = tk.Button(root, text="Click Me", command=_thread.start_new_thread(write_to_file, ())).pack()
create_img_list()
root.mainloop()

What is going on here and how do I fix it?

Upvotes: 1

Views: 269

Answers (1)

furas
furas

Reputation: 142681

When I add print(img_list) to write_to_file() I see that this function is executed at start - without clicking button - even before create_img_list() runs (which creates list) so write_to_file() writes empty list.

You use command= incorrectly. It needs function name without () (so called "callback") but you run function and you assign its result to command=. Your code works like

result = _thread.start_new_thread(write_to_file, ()) # it executes function at start

button = tk.Button(root, text="Click Me", command=result).pack()

but you need

def run_thread_later():
    _thread.start_new_thread(write_to_file, ())

button = tk.Button(root, text="Click Me", command=run_thread_later).pack()

Eventually you can uses lambda to create this function directly in command=

button = tk.Button(root, text="Click Me", command=lambda:_thread.start_new_thread(write_to_file, ())).pack()

BTW: you have common mistake

button = Button(...).pack()

which assign None to variable because pack()/grid()/place() return `None.

If you need access button later then you have to do it in two lines

button = Button(...)
button.pack()

If you don't need access button later then you can skip `button()

Button(...).pack()

Upvotes: 1

Related Questions