【问题标题】:How to cancel or pause a urllib request in python如何在python中取消或暂停一个urllib请求
【发布时间】:2020-07-26 08:40:44
【问题描述】:

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

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()

【问题讨论】:

  • 您可以通过reporthook 选项将回调关联到urllib.request.urlretrieve(),并通过在回调中引发异常来中止下载。
  • 你能举个例子吗?(如代码示例)

标签: python tkinter urllib urllib3 python-3.8


【解决方案1】:

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

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!,这样用户可以再次点击终止下载。当下载中止/完成时,其文本会变回“下载!”。

【讨论】:

  • 你好,acw1668。我已经尝试过你的代码,但我得到了一个像这样的语法错误:SyntaxError: no binding for nonlocal 'downloading' found。那么有没有办法解决这个问题呢?
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 2018-06-23
  • 1970-01-01
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-10
相关资源
最近更新 更多