2016-04-29 3 views
0

私は数週間同じ問題に悩まされています。私は自分の望むやり方を理解することができず、誰かが私を助けてくれることを望んでいます。ここ は、すべて私のコードのstart_auto_window_1セクションに常駐スレッドと私の問題は、以下のとおりです。私は同じ名前を持つ古いタイマーを消去したいタイマーを作成するときPythonスレッドオブジェクト

  1. 、私はそれをしたくありません毎回新しいスレッドを作成してください。私は彼らが "ID"を持っているようだが、私はそれを与えた名前で名前が付けられていないときにスレッドをキャンセルする方法を把握することはできません。

  2. 私は、プログラムを終了するとすべてのスレッドをキャンセルします。

私はプログラミングにかなり新しいですし、クラスにはるかに理解し、彼らはそこに期待してすることは簡単な答えが存在すると私は単に「、まだどのように動作するかすることはできません伝えることができます下に見ることで、明らかに注意してくださいそれを見つける。 あまりにも多くのコードを投稿して申し訳ありませんが、すべてをそこに置く方がよいと考えました。

また、誰かが私のプロジェクトに興味があり、一緒に仕事をしたいと思ったら教えてください!

import tkinter 
import time 
import socket 
import sys 
import threading 
from datetime import datetime 


#connection_status = tkinter.StringVar() 

try: 
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
except socket.error: 
    print("failed to create socket") 
    sys.exit() 


class Valve: 

    def __init__(self, pin, location): 
     self.pin = pin 
     self.location = location 

    timer = 0 
    status = False 
    auto = False 

    def turn_on(self): 
     self.status = True 
     self.send_info() 

    def turn_off(self): 
     self.status = False 
     self.send_info() 

    def set_timer(self, minutes): 
     self.timer = minutes * 60 

    def initiate(self): 
     if self.timer > 0: 
      self.auto = True 
      self.turn_on() 
      while self.timer > 0: 
       print(self.timer) 
       self.timer -= 1 
       time.sleep(1) 
      if self.auto is True: 
       self.turn_off() 
     elif self.timer == 0 and self.status is False: 
      self.auto = False 
      self.turn_on() 
     elif self.timer == 0 and self.status is True: 
      self.auto = False 
      self.turn_off() 

    def start(self): 
     thread = threading.Thread(target=self.initiate) 
     thread.start() 

    def send_info(self): 
     message_to_send = str(self.pin) + " " + str(self.status) 
     encoded_message_to_send = str.encode(message_to_send) 
     print(encoded_message_to_send) 
     my_socket.sendall(encoded_message_to_send) 


class Connection: 

    def __init__(self): 
     self.ip_address = "" 
     self.port_address = "" 
     self.connection_established = False 

    def connect(self): 
     try: 
      self.connection_established = True 
      my_socket.connect((self.ip_address, self.port_address)) 
      # connection_status.set("connected to: " + str(self.ip_address) + " " + str(self.port_address)) 
      print("Connected to:", self.ip_address) 
      print(my_socket) 

     except: 
      #connection_status.set("failed to connect to: " + str(self.ip_address) + " " + str(self.port_address)) 
      print("Not connected!") 
      self.connection_established = False 

    # def disconnect(self): 


root = tkinter.Tk() 

set_1_1_string_variable = tkinter.StringVar() 
seconds_start_1_1 = 0 
seconds_end_1_1 = 0 
set_1_2_string_variable = tkinter.StringVar() 


# functions for buttons 
def start1(): 
    if len(timer1.get()) != 0: 
     hose1.set_timer(0) 
     time.sleep(1.1) 
     timer_1_entry = int(timer1.get()) 
     hose1.set_timer(timer_1_entry) 
    if len(timer1.get()) == 0: 
     timer_1_entry = 0 
     hose1.set_timer(timer_1_entry) 
    hose1.start() 


def start2(): 
    if len(timer2.get()) != 0: 
     hose2.set_timer(0) 
     time.sleep(1.1) 
     timer_2_entry = int(timer2.get()) 
     hose2.set_timer(timer_2_entry) 
    if len(timer2.get()) == 0: 
     timer_2_entry = 0 
     hose2.set_timer(timer_2_entry) 
    hose2.start() 


def start3(): 
    if len(timer3.get()) != 0: 
     hose3.set_timer(0) 
     time.sleep(1.1) 
     timer_3_entry = int(timer3.get()) 
     hose2.set_timer(timer_3_entry) 
    if len(timer3.get()) == 0: 
     timer_3_entry = 0 
     hose3.set_timer(timer_3_entry) 
    hose3.start() 


def start4(): 
    if len(timer4.get()) != 0: 
     hose4.set_timer(0) 
     time.sleep(1.1) 
     timer_4_entry = int(timer4.get()) 
     hose4.set_timer(timer_4_entry) 
    if len(timer4.get()) == 0: 
     timer_4_entry = 0 
     hose4.set_timer(timer_4_entry) 
    hose4.start() 


# create class objects 
hose1 = Valve(9, 'Garden') 
hose2 = Valve(27, 'Lawn') 
hose3 = Valve(22, 'Patio') 
hose4 = Valve(10, 'Front') 

pi = Connection() 


# GUI layout 
def setup_window(): 
    # create host object and connect function from object's class 
    def connect_button(): 
     pi.ip_address = str(ip_entry.get()) 
     pi.port_address = int(port_entry.get()) 
     pi.connect() 

    connection_window = tkinter.Toplevel(root) 

    ip_label = tkinter.Label(connection_window, text="IP Address:", width=10, anchor='e') 
    port_label = tkinter.Label(connection_window, text="Port:", width=10, anchor='e') 
    ip_entry = tkinter.Entry(connection_window, width=15) 
    port_entry = tkinter.Entry(connection_window, width=15) 
    connect_to_server_button = tkinter.Button(connection_window, text='Connect', width=25, command=connect_button) 

    ip_label.grid(row=0, column=0) 
    port_label.grid(row=1, column=0) 
    ip_entry.grid(row=0, column=1) 
    port_entry.grid(row=1, column=1) 
    connect_to_server_button.grid(row=2, column=0, columnspan=2) 


def start_auto_1_window(): 

    global set_1_1_string_variable 

    def set1(): 
     def second_until(hour, minute): 
      today = datetime.today() 
      water_time = datetime.today() 
      water_time = water_time.replace(day=water_time.day+1, hour=hour, minute=minute) 
      answer = water_time - today 
      return answer.total_seconds() 

     #if pi.connection_established: 
     if True: 
      beginning_1_entry = beginning_1.get() 
      ending_1_entry = ending_1.get() 
      full_setup = 'Auto water is set for: ' + beginning_1_entry + ' to ' + ending_1_entry 
      begin_hour_1 = int(beginning_1_entry[:2]) 
      begin_minute_1 = int(beginning_1_entry[2:]) 
      end_hour_1 = int(ending_1_entry[:2]) 
      end_minute_1 = int(ending_1_entry[2:]) 

      if len(beginning_1_entry) == 4 and len(ending_1_entry) == 4 and begin_hour_1 < 24 and \ 
          begin_minute_1 < 60 and end_hour_1 < 24 and end_minute_1 < 60: 

       set_1_1_string_variable.set(full_setup) 
       global seconds_start_1_1 
       seconds_start_1_1 = second_until(begin_hour_1, begin_minute_1) 
       global seconds_end_1_1 
       seconds_end_1_1 = second_until(end_hour_1, end_minute_1) 
       print("starting in %d secs and ending in %d secs" % (seconds_start_1_1, seconds_end_1_1)) 
       thread1_1 = threading.Timer(int(seconds_start_1_1), hose1.turn_on) 
       thread1_2 = threading.Timer(int(seconds_end_1_1), hose1.turn_off) 
       thread1_3 = threading.Timer(int(seconds_end_1_1), set1) 
       thread1_1.start() 
       thread1_2.start() 
       thread1_3.start() 
       print(thread1_1) 
       print(thread1_2) 
       print(thread1_3) 
       print('starting threads') 
       print(threading.enumerate()) 

      else: 
       set_1_1_string_variable.set("use 24 hour clock (ex. 1230)") 
     #else: 
      #set_1_1_string_variable.set("Not connected to Pi") 

    auto_1_window = tkinter.Toplevel(root) 

    beginning_1 = tkinter.Entry(auto_1_window) 
    ending_1 = tkinter.Entry(auto_1_window) 
    set_1 = tkinter.Button(auto_1_window, text="Set", width=10, command=set1) 
    set_1_label = tkinter.Label(auto_1_window, width=30, textvariable=set_1_1_string_variable) 

    beginning_1.grid(row=0, column=0) 
    ending_1.grid(row=0, column=1) 
    set_1.grid(row=0, column=2) 
    set_1_label.grid(row=0, column=3) 

    beginning_2 = tkinter.Entry(auto_1_window) 
    ending_2 = tkinter.Entry(auto_1_window) 
    set_2 = tkinter.Button(auto_1_window, text="Set", width=10) 
    set_2_label = tkinter.Label(auto_1_window, width=30, textvariable=set_1_2_string_variable) 

    beginning_2.grid(row=1, column=0) 
    ending_2.grid(row=1, column=1) 
    set_2.grid(row=1, column=2) 
    set_2_label.grid(row=1, column=3) 

logo = tkinter.PhotoImage(file="v1.gif") 

top_frame = tkinter.Frame(root) 
bottom_frame = tkinter.Frame(root) 
top_frame.grid() 
bottom_frame.grid() 

# top_frame 
label = tkinter.Label(top_frame, text="Jason's Watering System", width=70) 
open_connection = tkinter.Button(top_frame, text="Connection setup", width=20, height=3, command=setup_window) 
photo_label = tkinter.Label(top_frame, image=logo) 
label.grid(row=0, column=0, columnspan=2, sticky='w') 
open_connection.grid(row=0, column=2, sticky='e') 
photo_label.grid(row=1, column=0, columnspan=3) 

# Bottom frame Headers 
pin_header = tkinter.Label(bottom_frame, text="Pin #", width=20) 
location = tkinter.Label(bottom_frame, text="Area", width=20) 
timer = tkinter.Label(bottom_frame, text='Timer (mins)', width=20) 
spacer = tkinter.Label(bottom_frame, width=20) 
black_spacer = tkinter.Label(bottom_frame, width=1, bg='black') 
auto = tkinter.Label(bottom_frame, text="Configure Auto", width=15) 

pin_header.grid(row=0, column=0) 
location.grid(row=0, column=1) 
timer.grid(row=0, column=2) 
spacer.grid(row=0, column=3) 
black_spacer.grid(row=0, column=4) 
auto.grid(row=0, column=5) 

# area 1 GUI 
pin1 = tkinter.Label(bottom_frame, text=int(hose1.pin)) 
location1 = tkinter.Label(bottom_frame, text=hose1.location) 
timer1 = tkinter.Entry(bottom_frame, width=8) 
button1 = tkinter.Button(bottom_frame, text="Start/Stop", command=start1, width=13) 
black_spacer1 = tkinter.Label(bottom_frame, width=1, bg='black') 
configure1 = tkinter.Button(bottom_frame, text='setup', command=start_auto_1_window) 


pin1.grid(row=1, column=0) 
location1.grid(row=1, column=1) 
timer1.grid(row=1, column=2) 
button1.grid(row=1, column=3) 
black_spacer1.grid(row=1, column=4) 
configure1.grid(row=1, column=5) 

# area 2 GUI 
pin2 = tkinter.Label(bottom_frame, text=int(hose2.pin)) 
location2 = tkinter.Label(bottom_frame, text=hose2.location) 
timer2 = tkinter.Entry(bottom_frame, width=8) 
button2 = tkinter.Button(bottom_frame, text="Start/Stop", command=start2, width=13) 
black_spacer2 = tkinter.Label(bottom_frame, width=1, bg='black') 
configure2 = tkinter.Button(bottom_frame, text='setup') 


pin2.grid(row=2, column=0) 
location2.grid(row=2, column=1) 
timer2.grid(row=2, column=2) 
button2.grid(row=2, column=3) 
black_spacer2.grid(row=2, column=4) 
configure2.grid(row=2, column=5) 

# area 3 GUI 
pin3 = tkinter.Label(bottom_frame, text=int(hose3.pin)) 
location3 = tkinter.Label(bottom_frame, text=hose3.location) 
timer3 = tkinter.Entry(bottom_frame, width=8) 
button3 = tkinter.Button(bottom_frame, text="Start/Stop", command=start3, width=13) 
black_spacer3 = tkinter.Label(bottom_frame, width=1, bg='black') 
configure3 = tkinter.Button(bottom_frame, text='setup') 


pin3.grid(row=3, column=0) 
location3.grid(row=3, column=1) 
timer3.grid(row=3, column=2) 
button3.grid(row=3, column=3) 
black_spacer3.grid(row=3, column=4) 
configure3.grid(row=3, column=5) 

# area 4 GUI 
pin4 = tkinter.Label(bottom_frame, text=int(hose4.pin)) 
location4 = tkinter.Label(bottom_frame, text=hose4.location) 
timer4 = tkinter.Entry(bottom_frame, width=8) 
button4 = tkinter.Button(bottom_frame, text="Start/Stop", command=start4, width=13) 
black_spacer4 = tkinter.Label(bottom_frame, width=1, bg='black') 
configure4 = tkinter.Button(bottom_frame, text='setup') 


pin4.grid(row=4, column=0) 
location4.grid(row=4, column=1) 
timer4.grid(row=4, column=2) 
button4.grid(row=4, column=3) 
black_spacer4.grid(row=4, column=4) 
configure4.grid(row=4, column=5) 


try: 
    root.mainloop() 
finally: 
    if pi.connection_established: 
     hose1.turn_off() 
     hose2.turn_off() 
     hose3.turn_off() 
     hose4.turn_off() 
     print("socket closed") 
     my_socket.close() 
     sys.exit() 

答えて

-1

多くの理由からマルチプロセッシングが好んでいますが、ここでは問題はありません。重要なことは、このプログラムがスレッド処理ではなくマルチプロセッシングを使用していることです。これは、クラスを使用する理由の優れた例です。 1つのクラスには、カウンタ/タイマに必要なものがすべて含まれています(カウンタは簡単のためにプログラムで使用されています)。別のカウンタを追加するには、クラスの別のインスタンスを作成します。このプログラムはすぐに2つのカウンター/クラスのインスタンスを作成しますので、2つのカウンター/クラスインスタンスの表示に違いはありませんが、これは単なる例です。終了ボタンが押されたときに呼び出される関数に注目してください。それはすべてのプロセス(オープンまたはクローズしてそれらに参加する)をシャットダウンし、すべてが適切に閉じられていることを確認するための良い考えです。

編集:プロセスからの、プロセスへの、プロセス間のやりとりが容易なマネージャオブジェクト(辞書)(​​マルチプロセッシングを使用する主な理由の1つ)。このプログラムはプロセスを停止し、終了ボタンが押されてから正常終了するまで、このプログラムは終了しません。これは、メモリが足りなくなった場合を除いて十分です。

キューを使用してカウンタを格納する別の更新プログラムです。これは、同様の質問をしている多くの人がいるので、これを正しくすることが重要です。あなたが_not_ここでマルチプロセッシング使用している

from multiprocessing import Process, Manager, Queue 
import time 

try: 
    import Tkinter as tk ## Python 2.x 
except: 
    import tkinter as tk ## Python 3.x 

class Counter(): 
    def __init__(self, root, process_num, test_d): 
     self.root=root 
     self.ctr=0 
     self.test_d=test_d 
     self.process_num=process_num 
     self.counter() 
     self.root.after(100, self.check_queue, q) 

    def counter(self): 
     """ a separate process in a separate GUI 
     """ 
     self.top_count=tk.Toplevel(self.root) 
     self.label_ctr = tk.IntVar() 
     self.label_ctr.set(self.ctr) 
     self.lab=tk.Label(self.top_count, textvariable=self.label_ctr, 
         width=20).grid() 
     tk.Button(self.top_count, text="Stop This Process", bg="orange", 
        command=self.stop_process).grid(row=3) 

    def check_queue(self, c_queue): 
     try: 
      s=c_queue.get(0) 
      self.label_ctr.set(s) 
     except: 
      pass 

     if self.test_d[self.process_num] == "True": 
      self.root.after(500, self.check_queue, c_queue) 

    def change_counter(self, q): 
     while self.test_d[self.process_num] == "True": 
      self.ctr += 1 
      q.put("%s" % (self.ctr)) 

      ## time.sleep() does not affect Tkinter because 
      ## it is in a separate process 
      time.sleep(1.0) 

    def stop_process(self): 
     test_d[self.process_num]="False" 

     ## uncomment the following line to destroy the window 
##  self.top_count.destroy() 

def exit_function(): 
    ## shut down Tkinter 
    root.quit() 
    exit_threads() 

def exit_threads(): 
    ## shut down the processes - more of a just to be sure 
    for this_process in list_of_processes: 
     this_process.terminate() 
     this_process.join() 

root = tk.Tk() 
tk.Button(root, text="Exit all", command=exit_function, bg="red").grid() 

## create two timers/class instances 
list_of_processes=[] 
manager = Manager() 
test_d = manager.dict() 
for ctr in ["one", "two"]: 
    test_d[ctr]="True" 

    q=Queue() 
    q.cancel_join_thread() 

    PB=Counter(root, ctr, test_d) 
    pr1=Process(name=ctr, target=PB.change_counter, args=(q,)) 
    pr1.start() 

    ## list of all processes which is used by the Exit button's call 
    list_of_processes.append(pr1) 

root.mainloop() 

## if the Tkinter app is closed without using the Exit button 
exit_threads() 
+0

は、 'プロセス(対象= self.counter()は、引数の=は())' '現在のプロセスでself.counterを()'を呼び出し、その後で新しいプロセスを開始しますその戻り値は「None」であり、新しいプロセスは何もしません。この場合のマルチプロセッシングの使用は実際には機能しません。別のプロセスから直接ローカルリソースにアクセスすることはできません。この場合、スレッディングは使用するのに適しています。 – mata

+0

これは確かに私が物事を別のやり方で見るのを助けてくれました。私はスレッド化モジュールの代わりに "マルチプロセッシング"モジュールについてもう少し研究をするつもりです。 – JayEli

+0

私はルーキーミスを犯しました(あまりにも急いで急いで)、プロセスに、プロセスから、プロセス間で通信するマネージャオブジェクトは含まれていませんでした。上記のコードは修正されました。プロセスの終了時ではなくプロセスが停止したときにプロセスを強制終了する必要がある場合は、新しい質問を投稿してください。これはそれ自体のトピックです。いくつかのソリューションがOSに依存するため、オペレーティングシステムを含めるようにしてください。 Doug Hellmannの今週のPythonモジュールで勉強を始めるhttps://pymotw.com/2/multiprocessing/index.html#module-multiprocessing –

関連する問題