Запускать и останавливать потоки с помощью цикла while

Я создаю графический интерфейс tkinter для получения входящих данных с устройства (через запрос) и добавляю их в файл csv, имея при этом предварительный просмотр этих данных.

Я использую thread, но с трудом понимаю его правильно, особенно как приостановить и перезапустить его.

Когда я нажимаю кнопку «Пуск», мои потоки работают правильно. Как только я пытаюсь нажать кнопку остановки потоковой передачи, моя переменная stop_threads изменяется на 0, однако цикл while в моем потоке не видит этого изменения. Ты знаешь почему?

Большое спасибо!

import tkinter as tk
import threading
from tkinter import ttk


def init_csv():
    pass
    # create my csv file here

def clear_data():
    tv1.delete(*tv1.get_children())
    init_csv()


def stream_data():
    global stop_threads
    IP_Machine = IP_entry.get()

    while True:
        if stop_threads == 1:
            print('Stream')
            # retrieve incoming data from my device (through request)
            # appending them into a csv file

        if stop_threads == 0:
            print('Pause')
            # I want to pause this thread here


def start_stream():
    t1_stream.start()
    stream_label['text'] = 'Streaming...'
    button_start.destroy()

    # Create stop streaming button
    button_stop = tk.Button(main_frame, text = "Stop Streaming", bg=Blue, fg=Bg_color, font='BOLD 12',
                            command=stop_stream)
    button_stop.place(relx=0.2, rely=0.14, relwidth=0.15, relheight=0.07)


def stop_stream():
    stop_threads = 0
    stream_label['text'] = ''

    # Create ReStart streaming button
    button_restart = tk.Button(main_frame, text = "Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12',
                               command=restart)
    button_restart.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07)


def restart():
    stop_threads = 1
    stream_label['text'] = 'Streaming...'


def curve():
    # show live plot data with matplot Funcanimation
    pass


def refresch_treeview():
    tv1.delete(*tv1.get_children())
    # define content of the treeview and refrech
    tv1.after(500, refresch_treeview)


csv_path = 'C:/Users/b/Desktop/testfile.csv'
init_csv()
global stop_threads
stop_threads = 1

# Multitasking definition
t1_stream = threading.Thread(target=stream_data)
t2_refresch = threading.Thread(target=refresch_treeview)

# My Tkinter interface bellow
root = tk.Tk()

# Variables
Bg_color = '#F2F2F2'
Blue = '#045FB4'
c_width = 1400
c_height = 700

# Template
canvas = tk.Canvas(root, height=c_height, width=c_width, bg=Bg_color)
canvas.pack()
left_frame = tk.Frame(root, bg=Blue)
left_frame.place(anchor='center', relx=0.05, rely=0.5, relwidth=0.002, relheight=0.9)
right_frame = tk.Frame(root, bg=Blue)
right_frame.place(anchor='center', relx=0.95, rely=0.5, relwidth=0.002, relheight=0.9)
top_frame = tk.Frame(root, bg=Blue)
top_frame.place(anchor='center', relx=0.5, rely=0.05, relwidth=0.9, relheight=0.004)
bottom_frame = tk.Frame(root, bg=Blue)
bottom_frame.place(anchor='center', relx=0.5, rely=0.95, relwidth=0.9, relheight=0.004)
main_frame = tk.Frame(root, bg=Bg_color)
main_frame.place(anchor='center', relx=0.5, rely=0.5, relwidth=0.8, relheight=0.8)
# Title
title = tk.Label(root, text='Data analysis', height=2, width=20, font='bold 18')
title.place(anchor='center', relx=0.50, rely=0.05)

# ENTRIES Definition
# Machine IP
IP_frame = tk.Frame(main_frame, bg=Bg_color)
IP_frame.place(relx=0, rely=0.05, relwidth=0.35, relheight=0.05)
IP_label = tk.Label(IP_frame, text='2000Xc IP address : ', font='12')
IP_label.pack(side='left', fill='y')
IP_entry = tk.Entry(IP_frame, width=22, font='12')
IP_entry.pack(side='right', fill='y')

# Streaming runing label
stream_label = tk.Label(main_frame, font='10', text='')
stream_label.place(anchor='w', relx=0, rely=0.45, relwidth=0.1, relheight=0.06)

# BUTTONS Definition
# Start streaming button
button_start = tk.Button(main_frame, text = "Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=start_stream)
button_start.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07)

# Clear data
button_clear = tk.Button(main_frame, text = "Clear data", bg=Blue, fg=Bg_color, font='BOLD 10', command=clear_data)
button_clear.place(relx=0.92, rely=0.9, relwidth=0.08, relheight=0.06)
# Show graph button
button_graph = tk.Button(main_frame, text = "Show curves", bg=Blue, fg=Bg_color, font='BOLD 10', command=curve)
button_graph.place(relx=0.6, rely=0.35, relwidth=0.1, relheight=0.05)

# csv preview
preview_frame = tk.Frame(main_frame, bg=Bg_color)
preview_frame.place(relx=0, rely=0.5, relwidth=1, relheight=0.4)
tv1 = ttk.Treeview(preview_frame)
tv1.place(relheight=0.95, relwidth=1)  # set the height and width of the widget to 100% of its container (frame1).
# scroll preview
treescrolly = tk.Scrollbar(preview_frame, orient = "vertical",
                           command=tv1.yview)  # command means update the yaxis view of the widget
treescrollx = tk.Scrollbar(preview_frame, orient = "horizontal",
                           command=tv1.xview)  # command means update the xaxis view of the widget
tv1.configure(xscrollcommand=treescrollx.set,
              yscrollcommand=treescrolly.set)  # assign the scrollbars to the Treeview Widget
treescrollx.pack(side = "bottom", fill = "x")  # make the scrollbar fill the x axis of the Treeview widget
treescrolly.pack(side = "right", fill = "y")  # make the scrollbar fill the y axis of the Treeview widget

t2_refresch.start()

root.mainloop()

Эй, Батист, вы получите лучшие ответы, если предоставите нам минимальный рабочий пример. Я не могу воспроизвести это напрямую, так как отсутствуют импорт и переменные.

Felix Kleine Bösing 10.12.2020 14:42

Эй, я добавляю в код детали, которые знают, что их можно запускать как есть. Моя проблема в том, что если вы нажмете кнопку запуска, она напечатает «Поток», что хорошо. Однако после этого, когда нажата кнопка «остановить поток», он продолжает печатать «Поток» вместо «Пауза».

Baptiste 10.12.2020 15:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны изменить только одну вещь. Вам нужно определить stop_threads как глобальный внутри функций. Затем Python знает, что вы ссылаетесь на глобальную переменную, а не создаете новую переменную внутри области действия локальной функции.

import tkinter as tk
import threading
from tkinter import ttk


def init_csv():
    pass
    # create my csv file here

def clear_data():
    tv1.delete(*tv1.get_children())
    init_csv()


def stream_data():
    global stop_threads
    IP_Machine = IP_entry.get()

    while True:
        if stop_threads == 1:
            print('Stream')
            # retrieve incoming data from my device (through request)
            # appending them into a csv file

        if stop_threads == 0:
            print('Pause')
            # I want to pause this thread here


def start_stream():
    t1_stream.start()
    stream_label['text'] = 'Streaming...'
    button_start.destroy()

    # Create stop streaming button
    button_stop = tk.Button(main_frame, text = "Stop Streaming", bg=Blue, fg=Bg_color, font='BOLD 12',
                            command=stop_stream)
    button_stop.place(relx=0.2, rely=0.14, relwidth=0.15, relheight=0.07)


def stop_stream():
    global stop_threads
    stop_threads = 0
    stream_label['text'] = ''

    # Create ReStart streaming button
    button_restart = tk.Button(main_frame, text = "Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12',
                               command=restart)
    button_restart.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07)


def restart():
    global stop_threads
    stop_threads = 1
    stream_label['text'] = 'Streaming...'


def curve():
    # show live plot data with matplot Funcanimation
    pass


def refresch_treeview():
    tv1.delete(*tv1.get_children())
    # define content of the treeview and refrech
    tv1.after(500, refresch_treeview)


csv_path = 'C:/Users/b/Desktop/testfile.csv'
init_csv()

stop_threads = 1

# Multitasking definition
t1_stream = threading.Thread(target=stream_data)
t2_refresch = threading.Thread(target=refresch_treeview)

# My Tkinter interface bellow
root = tk.Tk()

# Variables
Bg_color = '#F2F2F2'
Blue = '#045FB4'
c_width = 1400
c_height = 700

# Template
canvas = tk.Canvas(root, height=c_height, width=c_width, bg=Bg_color)
canvas.pack()
left_frame = tk.Frame(root, bg=Blue)
left_frame.place(anchor='center', relx=0.05, rely=0.5, relwidth=0.002, relheight=0.9)
right_frame = tk.Frame(root, bg=Blue)
right_frame.place(anchor='center', relx=0.95, rely=0.5, relwidth=0.002, relheight=0.9)
top_frame = tk.Frame(root, bg=Blue)
top_frame.place(anchor='center', relx=0.5, rely=0.05, relwidth=0.9, relheight=0.004)
bottom_frame = tk.Frame(root, bg=Blue)
bottom_frame.place(anchor='center', relx=0.5, rely=0.95, relwidth=0.9, relheight=0.004)
main_frame = tk.Frame(root, bg=Bg_color)
main_frame.place(anchor='center', relx=0.5, rely=0.5, relwidth=0.8, relheight=0.8)
# Title
title = tk.Label(root, text='Data analysis', height=2, width=20, font='bold 18')
title.place(anchor='center', relx=0.50, rely=0.05)

# ENTRIES Definition
# Machine IP
IP_frame = tk.Frame(main_frame, bg=Bg_color)
IP_frame.place(relx=0, rely=0.05, relwidth=0.35, relheight=0.05)
IP_label = tk.Label(IP_frame, text='2000Xc IP address : ', font='12')
IP_label.pack(side='left', fill='y')
IP_entry = tk.Entry(IP_frame, width=22, font='12')
IP_entry.pack(side='right', fill='y')

# Streaming runing label
stream_label = tk.Label(main_frame, font='10', text='')
stream_label.place(anchor='w', relx=0, rely=0.45, relwidth=0.1, relheight=0.06)

# BUTTONS Definition
# Start streaming button
button_start = tk.Button(main_frame, text = "Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=start_stream)
button_start.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07)

# Clear data
button_clear = tk.Button(main_frame, text = "Clear data", bg=Blue, fg=Bg_color, font='BOLD 10', command=clear_data)
button_clear.place(relx=0.92, rely=0.9, relwidth=0.08, relheight=0.06)
# Show graph button
button_graph = tk.Button(main_frame, text = "Show curves", bg=Blue, fg=Bg_color, font='BOLD 10', command=curve)
button_graph.place(relx=0.6, rely=0.35, relwidth=0.1, relheight=0.05)

# csv preview
preview_frame = tk.Frame(main_frame, bg=Bg_color)
preview_frame.place(relx=0, rely=0.5, relwidth=1, relheight=0.4)
tv1 = ttk.Treeview(preview_frame)
tv1.place(relheight=0.95, relwidth=1)  # set the height and width of the widget to 100% of its container (frame1).
# scroll preview
treescrolly = tk.Scrollbar(preview_frame, orient = "vertical",
                           command=tv1.yview)  # command means update the yaxis view of the widget
treescrollx = tk.Scrollbar(preview_frame, orient = "horizontal",
                           command=tv1.xview)  # command means update the xaxis view of the widget
tv1.configure(xscrollcommand=treescrollx.set,
              yscrollcommand=treescrolly.set)  # assign the scrollbars to the Treeview Widget
treescrollx.pack(side = "bottom", fill = "x")  # make the scrollbar fill the x axis of the Treeview widget
treescrolly.pack(side = "right", fill = "y")  # make the scrollbar fill the y axis of the Treeview widget

t2_refresch.start()

root.mainloop()

О, чувак, большое спасибо, я боролся с этим в течение 2 дней, и это была только эта мелочь.. Мне жаль, что я побеспокоил вас, ребята, из-за такой маленькой проблемы, но это помогает мне каждый раз узнавать больше! Спасибо. большое спасибо за поддержку, теперь работает нормально!

Baptiste 11.12.2020 08:37

Добро пожаловать. Вот для чего нужен stackoverflow :)

Felix Kleine Bösing 11.12.2020 17:48

Другие вопросы по теме