ashish
ashish

Reputation: 126

how to stop request.get in python

i have made a tkinter application on which i have a submit button, when i press this button a crawl request goes to request.get(url) method and it starts with the crawling and the tkinter becomes inactive untill it gives me the response. but i want another button "stop" in tkinter app which when pressed stops the process going in the background and next time i want i can press the submit button to again start the process. i have tried destroy and quit methods available in tkinter but they closes the tkinter widget itself. my code is :-

#!/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()

basically i am calling find_links function which is present in sepearte file and have the function request.get to crawl the links, presently i am not using threads.So, is there any way to stop this process without using threads. i dont want to pause it i just want to kill this process.

Upvotes: 1

Views: 2785

Answers (1)

Pythonista
Pythonista

Reputation: 11645

You can use a thread to start the scraping / crawling in another thread and then create a pause / resume button that enables "pausing" and "unpausing" the spawned threads through the thread methods threading.Condition and threading.Lock()

Example of one way to set the threads up, didn't create the gui or anything just showed an example of how to use a pauseable thread with a button click in your GUI since how you choose to setup / incorporate the threads will differ. This assumes pausing and resuming will occur after the thread is finished processing the current request.get call. Trying to stop a thread dead middle of a task is an entirely different issue unto itself.

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

Upvotes: 2

Related Questions