Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中是否有停止或取消URL检索的方法?_Python_Tkinter_Urllib_Urllib3_Cancel Button - Fatal编程技术网

在python中是否有停止或取消URL检索的方法?

在python中是否有停止或取消URL检索的方法?,python,tkinter,urllib,urllib3,cancel-button,Python,Tkinter,Urllib,Urllib3,Cancel Button,因此,我基本上已经用python编写了一个程序,使用tkinter和urllib.request,该程序应该作为一个下载程序,但每个下载程序都必须有一个暂停或取消按钮,但我似乎找不到任何方法来执行此操作!最近我在stackoverflow(链接:)中遇到了同样的问题,似乎我必须使用线程或多处理,但我一点也不知道如何做到这一点!顺便问一下,线程或多重处理如何帮助取消暂停下载?有人能给我解释一下我该怎么办吗?在没有线程或多处理的情况下,是否仍可以执行此操作?如果没有,你能解释一下如何在这个程序中使用

因此,我基本上已经用python编写了一个程序,使用tkinter和urllib.request,该程序应该作为一个下载程序,但每个下载程序都必须有一个暂停或取消按钮,但我似乎找不到任何方法来执行此操作!最近我在stackoverflow(链接:)中遇到了同样的问题,似乎我必须使用线程或多处理,但我一点也不知道如何做到这一点!顺便问一下,线程或多重处理如何帮助取消暂停下载?有人能给我解释一下我该怎么办吗?在没有线程或多处理的情况下,是否仍可以执行此操作?如果没有,你能解释一下如何在这个程序中使用线程或多重处理吗?因为我一点都不知道该怎么做!请帮我解决这个问题。 我的代码:


在单个线程或进程中运行类似于
urlretrieve
的函数时,无法停止它,因为只有一个线程或进程

在本例中,您正在从
tkinter
回调调用
urlretrieve
。tkinter从
mainloop
调用这些函数,有效地中断了
mainloop

这对于通过快速连接从主机上进行少量下载可能不是问题。但是如果下载需要几秒钟或几分钟,那么您就有问题了。因为当
urlretrieve
正在进行时,您的GUI没有响应,因为
mainloop
正在等待您的回调完成

因此,即使您有一个“取消”按钮,只要
urlretrieve
正在运行,它也不会响应als

从Python目录中的文件
urllib/request.py
中读取
urlretrieve
函数。这不是一个大功能,应该相对容易理解。 在内部,
urlretrieve
包含一个循环,该循环从URL读取
s并写入文件。默认情况下,这样的读取会等到有任何东西要读取。事情是这样的;没有办法中断这个循环

因此,无论如何,您必须重新编写urlretrieve。在这个重新编写的版本中,如果应该继续,您应该检查内部循环的每个迭代

你基本上有两个选择

  • urlretrieve
    的功能放入事件循环中
  • urlretrieve
    的功能放到不同的线程中
  • 各有利弊。如果您使用的是Python3,那么启动
    threading.Thread
    可能是最容易的事情,因为Python3中的
    tkinter
    是线程安全的

    有关第一种方法的示例,请参见github上的脚本repo。在此应用程序中,长操作分为几个小步骤,这些步骤通过
    after
    方法从
    tkinter
    eventloop调用


    对于使用线程的方法,我手头没有一个示例。基本上,您必须重写
    urlretrieve
    来检查一个变量(例如
    threading.Event
    ),该变量在
    内部循环时发出是否应该停止的信号。

    因为Python 3中的tkinter是线程安全的:您对此有参考吗?@stovfl请参阅。引用:“此外,内部模块\u tkinter提供了一种线程安全机制,允许Python和Tcl进行交互。”@stovfl事实证明,从多年来提出的不同相关问题来看,这并非无条件正确。事实似乎比二进制的是/否更复杂。这里有一些关于stackoverflow的例子,从不同线程调用tkinter函数可以很好地工作“穿线情况很复杂。Tcl不是线程安全的,除非配置了--enable threads。。。可以从其他线程调用命令_tkinter将为解释器线程“@stovfl”排队。在我的平台上,默认情况下会生成线程tkinter。这是否回答了您的问题?
    from tkinter import *
    from tkinter import font as tkFont
    import random
    import urllib.request
    import requests
    
    
    def printsth():
        print("Yay it works! ")
    
    
    def main_menu():
        root = Tk()
        root.title('8-bit downloader ')
        root.iconbitmap(r"C:\Users\rayanravesh\PycharmProjects\GUI_Calculator\icon.ico")
        root.geometry("600x280")
        # the top menu
        num = IntVar()
        chum = IntVar()
        # var = IntVar()
        menu = Menu(root)
        root.config(menu=menu)
        submenu = Menu(menu)
        menu.add_cascade(label="Settings", menu=submenu)
    
        def custom_op():
            custom = Toplevel()
            custom.iconbitmap(r"C:\Users\rayanravesh\PycharmProjects\GUI_Calculator\icon.ico")
        submenu.add_command(label="Customization ", command=custom_op)
    
        def settings_op():
            global gps
            set_win = Toplevel()
            set_win.iconbitmap(r"C:\Users\rayanravesh\PycharmProjects\GUI_Calculator\icon.ico")
            path_label = Label(set_win, text="Current default download path: ")
            path_entry = Entry(set_win, width=30)
            file_read = open('Data.txt', 'r')
            data_base = file_read.read()
            path_entry.insert(0, data_base)
            file_read.close()
    
            def default_output():
                global location
                file_read2 = open('Data.txt', 'r+')
                file_read2.truncate(0)
                file_read2.close()
                write_file2 = open('Data.txt', 'w')
                write_file2.write(path_entry.get())
                write_file2.close()
                location = path_entry.get() + "\\"
                default_location = location.replace("\\", "\\\\")
            path_btn = Button(set_win, text="Submit ", command=default_output)
            path_label.pack(anchor=CENTER, expand=1)
            path_entry.pack(anchor=CENTER, expand=1)
            path_btn.pack(anchor=CENTER, expand=1)
        submenu.add_command(label="Settings ", command=settings_op)
        submenu.add_separator()
        submenu.add_command(label="Exit", command=root.destroy)
    
        # the section menu
        editmenu = Menu(menu)
        menu.add_cascade(label="Sections(soon)", menu=editmenu)
        editmenu.add_command(label="Downloader", command=printsth)
        editmenu.add_command(label="Converter", command=printsth)
        editmenu.add_command(label="Media Player", command=printsth)
        editmenu.add_command(label="Editor", 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, 1000000)
            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()
            if chum.get() == 1:
                filee = open('Data.txt', 'r')
                destination = filee.read()
                path = destination
                output_entry.insert(0, destination)
                filee.close()
            else:
                output_entry.delete(0, END)
                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, width=30)
        label = Label(inter_frame, text="Enter the image URL: ")
        file_format = Label(inter_frame, text="Choose your file format: ")
        format_entry = Entry(inter_frame, width=30)
        file_name = Label(inter_frame, text="File's name: ")
        name_entry = Entry(inter_frame, width=30)
        check_name = Checkbutton(inter_frame, text="Give a random name", variable=num)
        # check_format = Checkbutton(inter_frame, text="Download with default format", variable=var)
        check_default = Checkbutton(inter_frame, text="Download to default path", variable=chum)
        output_path = Label(inter_frame, text="Choose output path: ")
        output_entry = Entry(inter_frame, width=30)
        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)
        format_entry.insert(0, '.')
        # check_format.pack(anchor=CENTER)
        output_path.pack(anchor=CENTER, expand=1)
        output_entry.pack(anchor=CENTER, expand=1)
        check_default.pack(anchor=CENTER, expand=1)
        inter_frame.pack(expand=1)
        root.mainloop()
    
        # the end!
    
    
    main_menu()