如何在python中取消或暂停urllib请求 [英] How to cancel or pause a urllib request in python

查看:86
本文介绍了如何在python中取消或暂停urllib请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这个程序,它从网上请求一个文件,用户可以下载它.我正在为我的程序使用 urllib.request 和 tkinter.问题是,当用户点击下载"按钮时,在文件下载并且程序也冻结之前不会暂停或取消.我真的很想创建一个暂停或取消按钮,但我不知道如何并且我想消除程序的冻结.我应该使用另一个像请求"这样的库吗?或者我应该尝试线程?有人可以指导我完成这个吗?我的代码(顺便说一句,如果您知道任何改进我的程序的方法,如果您与我分享,我将不胜感激):

So I have this program which requests a file from the web and the user can download it. I am using urllib.request and tkinter for my program. The problem is that when the user hits the 'Download' button there is no pause or cancel until the file gets downloaded and the program freezes too. I really want to create a pause or a cancel button, but I do not know how and I want to eliminate the freezing of the program. Should I use another library like 'requests'? Or should I try threading? Can someone guide me through this? My code(BTW if you know any way to improve my program I would appreciate it a lot if you shared it with me):

from tkinter import *
from tkinter import font as tkFont
import random
import urllib.request
import requests
from tqdm import tqdm
from tqdm.auto import tqdm


def printsth():
    print("Yay it works! ")


def main_menu():
    root = Tk()
    # the top menu
    num = IntVar()
    # var = IntVar()
    menu = Menu(root)
    root.config(menu=menu)
    submenu = Menu(menu)
    menu.add_cascade(label="Settings", menu=submenu)

    def custom_op():
        custom = Tk()

        custom.mainloop()
    submenu.add_command(label="Customization ", command=custom_op)

    def settings_op():
        set_win = Tk()

        set_win.mainloop()
    submenu.add_command(label="Settings ", command=settings_op)
    submenu.add_separator()
    submenu.add_command(label="Exit", command=root.destroy)

    # the edit menu
    editmenu = Menu(menu)
    menu.add_cascade(label="Edit", menu=editmenu)
    editmenu.add_command(label="Redo...", command=printsth)

    # the tool bar
    toolbar = Frame(root, bg="light gray")
    insert_button = Button(toolbar, text="Insert an image", command=printsth)
    insert_button.pack(side=LEFT, padx=2, pady=2)
    print_button = Button(toolbar, text="Print", command=printsth)
    print_button.pack(side=LEFT, padx=2, pady=2)
    toolbar.pack(side=TOP, fill=X)

    # the download function
    def download_image():
        global formatname
        if num.get() == 1:
            name = random.randrange(1, 100000)
        else:
            name = str(name_entry.get())
        formatname = str(format_entry.get())
        '''if var.get() == 1:
            operator = str(url_entry.get())
            formatname = '.' + operator[-3] + operator[-2] + operator[-1]
        else:
            pass'''
        fullname = str(name) + formatname
        url = str(url_entry.get())
        fw = open('file-size.txt', 'w')
        file_size = int(requests.head(url, headers={'accept-encoding': ''}).headers['Content-Length'])
        fw.write(str(file_size))
        fw.close()
        path = str(output_entry.get()) + "\\"
        urllib.request.urlretrieve(url, path.replace("\\", "\\\\") + fullname)

    # the status bar
    status_bar = Label(root, text="Downloading...", bd=1, relief=SUNKEN, anchor=W)
    status_bar.pack(side=BOTTOM, fill=X)

    # the download frame
    body_frame = Frame(root, bg="light blue")
    download_button = Button(body_frame, text="Download! ", command=download_image, border=3, width=20, height=5)
    download_design = tkFont.Font(size=12, slant='italic')
    download_button['font'] = download_design
    download_button.pack(side=LEFT, pady=5, padx=5)
    body_frame.pack(side=LEFT, fill=Y)
    # the main interaction menu
    inter_frame = Frame(root)
    url_entry = Entry(inter_frame)
    label = Label(inter_frame, text="Enter the image URL: ")
    file_format = Label(inter_frame, text="Choose your file format: ")
    format_entry = Entry(inter_frame)
    file_name = Label(inter_frame, text="File's name: ")
    name_entry = Entry(inter_frame)
    check_name = Checkbutton(inter_frame, text="Give a random name", variable=num)
    # check_format = Checkbutton(inter_frame, text="Download with default format", variable=var)
    output_path = Label(inter_frame, text="Choose output path: ")
    output_entry = Entry(inter_frame)
    file_name.pack(anchor=CENTER, expand=1)
    name_entry.pack(anchor=CENTER, expand=1)
    check_name.pack(anchor=CENTER, expand=1)
    label.pack(anchor=CENTER, expand=1)
    url_entry.pack(anchor=CENTER, expand=1)
    file_format.pack(anchor=CENTER, expand=1)
    format_entry.pack(anchor=CENTER, expand=1)
    # check_format.pack(anchor=CENTER)
    output_path.pack(anchor=CENTER, expand=1)
    output_entry.pack(anchor=CENTER, expand=1)
    inter_frame.pack(expand=1)
    root.mainloop()

    # the end!


main_menu()

推荐答案

您可以使用 urllib.request.urlretrieve()reporthook 选项来关联回调和中止通过在回调中引发异常来下载:

You can use reporthook option of urllib.request.urlretrieve() to associate a callback and abort the download by raising exception inside the callback:

downloading = False   # flag to indicate whether download is active

def download_progress(count, blksize, filesize):
    nonlocal downloading
    if downloading:
        downloaded = count * blksize
        print('downloaded %s / %s' % (downloaded, filesize))
        root.update()  # let user interact with the GUI
    else:
        # user selects to abort the download
        raise Exception('download aborted!')

# the download function
def download_image():
    global formatname
    nonlocal downloading
    if downloading:
        downloading = False
        return
    download_button.config(text='Stop!')  # let user to click the button to abort download
    downloading = True
    if num.get() == 1:
        name = random.randrange(1, 100000)
    else:
        name = str(name_entry.get())
    formatname = str(format_entry.get())
    '''if var.get() == 1:
        operator = str(url_entry.get())
        formatname = '.' + operator[-3] + operator[-2] + operator[-1]
    else:
        pass'''
    fullname = str(name) + formatname
    url = str(url_entry.get())
    fw = open('file-size.txt', 'w')
    file_size = int(requests.head(url, headers={'accept-encoding': ''}).headers['Content-Length'])
    fw.write(str(file_size))
    fw.close()
    path = str(output_entry.get()) + "\\"
    try:
        urllib.request.urlretrieve(url, path.replace("\\", "\\\\")+fullname, download_progress)  # added reporthook callback
    except Exception as e:
        print(e)  # download aborted
    else:
        print('done')
    download_button.config(text='Download!')  # resume download button

download_button 的文字在被点击后变成了Stop!,这样用户可以再次点击它来中止下载.下载中止/完成后,其文本将更改回下载!".

The text of download_button is changed to Stop! after it is clicked so that user can click it again to abort the download. When the download is aborted/completed, its text is changed back to "Download!".

这篇关于如何在python中取消或暂停urllib请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆