2016-04-05 22 views
1

私は送信ボタンがあるtkinterアプリケーションを作成しました。このボタンを押すと、要求がrequest.get(url)メソッドに送られ、クロールが開始され、 tkinterは私に応答を与えるまで非アクティブになります。しかし、別のボタンをtkinterアプリで停止させたい場合は、押されたときにプロセスがバックグラウンドで停止し、次回は、送信ボタンを押してプロセスを再開したい場合があります。 私はtkinterで利用可能なメソッドを破壊して終了しようとしましたが、tkinterウィジェット自体を閉じます。 私のコードは次のとおりです。 - 、基本的に私はsepearteファイルに存在するfind_links関数を呼び出すとリンクをクロールする機能request.getを持って、現在、私はthreads.Soを使用していないのですpythonでrequest.getを停止する方法

#!/usr/bin/python 
# -*- coding: latin-1 -*- 
from Tkinter import * 
import thread 
from tool_crawler import * 
import tkMessageBox 
import ttk 

# function which accepts url from GUI and pass it further for the 
def crawl(url): 
    time_delay = time_delay_box.get() 

    if url == "Please enter URL.......": 
     tkMessageBox.showerror("Error(错误)", "Please enter a valid URL(请输入有效网址)") 

    elif not url: 
     tkMessageBox.showerror("Error(错误)", "Please enter a valid URL(请输入有效网址)") 


    else: 
     tree.heading("#0", text=url) 
     links = find_links(url, time_delay) 
     #print links 
     for i, link in enumerate(links): 
      tree.insert("", i, str(i), text=link) 
      tree.bind("<Double-1>", OnDoubleClick) 

# function will invoke when any node in tree is double clicked  
def OnDoubleClick(event): 
     item = tree.identify('item',event.x,event.y)   
     url = tree.item(item,"text") 
     index = tree.index(item) 
     parent = tree.parent(item) 
     crawl_child(url,index,parent) 


def crawl_child(url,index,parent): 
    links = find_links(url, time_delay) 
    #print links 
    for i, link in enumerate(links): 
     if not parent: 
      tree.insert(str(index), i, str(index)+"."+str(i), text=link) 
     else: 
      tree.insert(str(parent)+"."+str(index), i, str(parent)+"."+str(index)+"."+str(i), text=link) 

# tkinter object 
top = Tk() 
top.configure(background='Lavender') 

# window title 
top.title("Fan Wan Crawler ") 

# tkinter minimum and maximum size 
top.minsize(width=1460, height=800) 
top.maxsize(width=1460, height=800) 

# url entry area i.e. text box to enter the URLS 
url = Entry(top, bd =3, width = 180) 
url.insert(0, "Please enter URL.......") 
url.pack(side = TOP) 

# function to show and hide the text on entry and exit 
def default(event): 
    current = url.get() 
    if current == "Please enter URL.......": 
     url.delete ("0", END) 
    elif not current: 
     url.insert("0", "Please enter URL.......") 

# code to call function default on focusin and focusout 
url.bind("<FocusIn>", default) 
url.bind("<FocusOut>", default) 

# submit button which is performing action on submit 
submit = Button(top, text="Submit(提交)", width=15, bg='lightblue', command=lambda: crawl(url.get())) 
submit.pack(side = TOP) 

# time delay label 
time_label = Label(top, text="Time Dealy (时间延迟):", font= ("Helvetica", 12), bg="Lavender", fg = "green") 
time_label.place(x=2, y=27) 

# time delay Entry 
time_delay_box = Spinbox(top, from_=0, to=100, width=3) 
time_delay_box.place(x=175, y=27) 

# time description 
time_label = Label(top, text="(in sec.(以秒为单位))", font=("Helvetica", 12), bg="Lavender", fg = "green") 
time_label.place(x=220, y=27) 

# tree area 
tree = ttk.Treeview(top, selectmode="browse", height= "36") 
columns = tree.column("#0", minwidth=0, width=720, stretch=True) 

tree.place(x=2,y=56) 

top.mainloop() 

どのような方法がありますスレッドを使用せずにこのプロセスを停止します。私はそれを一時停止したくないだけ私はこのプロセスを殺すしたい。

答えて

1

あなたが別のスレッドでクロール/スクレイピングを開始するためにthreadを使用し、「一時停止」とスレッドの方法で生成されたスレッドを「一時停止の解除」threading.Conditionthreading.Lock()

例を可能にし、一時停止/再開ボタンを作成することができますGUIを作成していないか、GUIのボタンをクリックしてポーズ可能なスレッドを使用する方法の例を示しただけです。どのように設定/組み込みを選択するかは異なるためです。これは、スレッドが現在のrequest.getコールの処理を終了した後に一時停止し、再開が発生することを前提としています。タスクの途中でスレッドを停止しようとする試みは、全く別の問題です。

import threading, requests 
import tkinter as tk 

def switch_thread_states(widget): 

    #or whatever pause/resume text you wish for the widget/button 
    if widget['text'] == 'Pause' 
     widget['text'] = 'Resume' 
    else: 
     widget['text'] = 'Pause' 
    for thread in threading.enumerate(): 
     if not isinstance(thread, threading._MainThread): 
      if thread.paused: 
       thread.resume() 
      else: 
       thread.pause() 

class PauseableThread(threading.Thread): 

    def __init__(self, urls): 

     threading.Thread.__init__(self) 
     self.urls = urls 
     self.paused = False 
     self.pause_cond = threading.Condition(threading.Lock()) 

    def run(self): 

     for url in self.urls: 

      with self.pause_cond: 
       while self.paused: 
        self.pause_cond.wait() 
      #make requests here or whatever you're doing 
      requests.get(url, headers={'User-Agent':'Mozilla/5.0 .....'}) 

    def pause(self): 

     self.paused = True 
     self.pause_cond.acquire() 

    def resume(self): 

     self.paused = False 
     self.pause_cond.notify() 
     self.pause_cond.release() 

    #make root 
    #make a button that calls switch_thread_states on press 
    #spawn threads with urls lists etc 
+0

答えに感謝しますが、私は、私はちょうどリンクをクロールするrequest.getメソッドを使用してthatsの他のファイルに存在クロール機能find_linksを呼び出しています現在、それは、現在実行中のプロセスを強制終了することが可能であるスレッドを使用していません直接 。これでも、プロセスが実行され、必要に応じて誰かがクリックできるようにするためのボタンを停止するまで、tkinterは非アクティブになります。私はコードを更新しました。 – ashish

+0

プロセスをGUIのイベントスレッドで実行させることはできず、ボタンを別のスレッドやhttps://docs.python.org/2/library/subprocess.htmlに入れずにアクティブなままにすることはできません。他の関数を呼び出すと、処理が終了するまでGUIのイベントスレッドがブロックされ、停止ボタンをクリックすることができなくなります。 'root.after'のようなものを試してみてください。ここでrootはあなたの関数を呼び出すためのメインのtkウィンドウですが、処理中はブロックされます。 – Pythonista

+0

ああ、それは良いと思うが、tkinterは、プロセスを停止する直接的な方法を提供していません。私は間にrequest.get呼び出しを停止したいと思います。 – ashish

関連する問題