- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 tkinter 和 urllib 制作这个程序,它应该像一个下载管理器。在我几乎完成该程序后,我意识到我没有为下载定义取消按钮。在深入研究之后,我发现了多处理(在此之前我只是使用线程),显然它是一个比并行运行函数的线程更好的模块,而且它还有一个终止函数。但是,无论我做什么,我似乎都无法理解这个模块。它比线程复杂得多,而且我总是会遇到荒谬的错误。在我的程序中,我经常遇到这个错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/Family/PycharmProjects/8-bit Downloader/test.py", line 258, in start_download
Process(target=download_files,
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 327, in _Popen
return Popen(process_obj)
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_tkinter.tkapp' object
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Users\Family\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
我完全不知道是什么原因导致了这个错误以及如何解决它。 start_download() 函数似乎有问题。我的代码(我知道它有一些缺陷,我可以使它更清晰,我只是想在完成基础知识后这样做,如果您认为某些部分不相关,请告诉我。):
import os
import sqlite3
import time
import urllib.request
from multiprocessing import Process
from pathlib import Path
from tkinter import *
from tkinter import filedialog
from tkinter import font
from tkinter import messagebox
from tkinter import ttk
import numpy as np
import requests
import win10toast
from PIL import Image, ImageTk
files_downloading, times_clicked, dir_files = 0, 0, {}
info_window, customize = None, None
# The problem I believe is with the two functions below and the start function some of the code is related to the downloads tab
# which is irrelevant and some other were just functions that were unrelated so if you see a button without a function that
# exists or it is 'None' it is just deleted for the purpose of this question and also ignore the image variables!
def get_info(path, new_fullname, url_entry):
global times_clicked
lbl_await.pack_forget()
prg_br.pack_forget()
file_size = int(requests.head(str(url_entry.get()),
headers={'accept-encoding': ''}).headers['Content-Length']) / 1000000
print(file_size)
file_dir = Path(str(path).replace(" \ ".strip(), "/") + "/" + new_fullname)
size_eachsec = np.array([0.0, ])
my_scrollbar.pack(side=RIGHT, fill=Y)
lbl_fr = ttk.LabelFrame(second_frame, text=new_fullname, padding=5)
if len(new_fullname) > 20:
lbl_fr.config(text=new_fullname[:21] + "...")
download_prg = ttk.Progressbar(lbl_fr, orient=HORIZONTAL, length=365, mode='determinate', cursor="wait")
lbl_speed = Label(lbl_fr, text=None)
lbl_crnt_size = Label(lbl_fr, text=None)
lbl_file_size = Label(lbl_fr, text=f"File size: {round(file_size, 3)} MB")
lbl_percent = Label(lbl_fr, text="0 %")
lbl_cancel_btn = ttk.Button(lbl_fr, image=cancel_btn_icon)
lbl_see_more = Label(second_frame, text="See more", fg="grey", font=("Arial", 10))
download_prg.grid(row=0, column=0, columnspan=2)
lbl_speed.grid(row=0, column=2, padx=5)
lbl_crnt_size.grid(row=1, column=1)
lbl_file_size.grid(row=1, column=0)
lbl_percent.grid(row=1, column=2)
lbl_cancel_btn.grid(row=0, column=3, rowspan=2)
lbl_fr.grid(row=times_clicked, column=0, padx=5, pady=5)
lbl_see_more.grid(row=times_clicked, column=1, padx=3)
times_clicked += 1
start_time = time.time()
while True:
if file_dir.exists():
time.sleep(0.5)
crnt_size = file_dir.stat().st_size / 1000000
size_eachsec = np.append(size_eachsec, crnt_size)
percent = (crnt_size / file_size) * 100
crnt_speed = size_eachsec[1] - size_eachsec[0]
size_eachsec = np.delete(size_eachsec, 0)
lbl_speed.config(text=f"{round(crnt_speed, 2)} MB/s")
lbl_crnt_size.config(text=f"Downloaded: {round(crnt_size, 3)} MB")
lbl_percent.config(text=f"{round(percent, 2)} %")
download_prg["value"] = percent
# print( f"Current Size: {crnt_size}, Current speed: {crnt_speed}, File size: {file_size},
# Percentage: {percent}% " f", Progress bar: {download_prg['value']}%")
if crnt_size == file_size:
break
end_time = time.time()
time_elapsed = end_time - start_time
print(f"Start time: {start_time}, End time: {end_time}, Time took: {time_elapsed}")
download_prg.config(cursor="arrow")
lbl_speed.config(text="Completed!")
def show_info(event):
global info_window
if info_window is not None and info_window.winfo_exists():
info_window.focus_set()
lbl_see_more.config(fg="purple")
else:
lbl_see_more.config(fg="purple")
info_window = Toplevel()
info_window.resizable(0, 0)
lbl_time_took = Label(info_window, text=f"Time elapsed: {round(time_elapsed, 2)}")
lbl_avg_speed = Label(info_window, text=f"Average speed: {round(file_size / time_elapsed, 3)} MB/s")
lbl_time_took.pack(pady=20)
lbl_avg_speed.pack(pady=20)
lbl_see_more.bind("<Button-1>", show_info)
new_font = font.Font(lbl_see_more, lbl_see_more.cget("font"))
new_font.configure(size=10, underline=True)
lbl_see_more.config(font=new_font, fg="blue", cursor="hand2")
print("Download successful! ")
def download_files(status_bar, url_entry, output_entry, name_entry, format_entry, num, chum, var):
global files_downloading
files_downloading += 1
status_bar.config(text=f"Downloading {files_downloading} file(s)...")
url = str(url_entry.get())
if num.get() == 1:
name = url.split("/")[-1].split(".")[0]
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
static_fullname = str(name) + formatname
new_fullname = static_fullname
path = (str(output_entry.get()) + "/").replace(" \ ".strip(), "/")
if chum.get() == 1:
conn = sqlite3.connect("DEF_PATH.db")
c = conn.cursor()
c.execute("SELECT * FROM DIRECTORY_LIST WHERE SELECTED_DEF = 1")
crnt_default_path = c.fetchall()
# print(crnt_default_path)
path = str(crnt_default_path[0][0] + "/").replace(" \ ".strip(), "/")
conn.commit()
conn.close()
else:
pass
if path + static_fullname not in dir_files.keys():
dir_files[path + static_fullname] = 0
all_files_dir = os.listdir(path)
# if fullname in all_files_dir:
while new_fullname in all_files_dir:
dir_files[path + static_fullname] += 1
if num.get() == 1:
name = url.split("/")[-1].split(".")[0] + f" ({dir_files.get(path + static_fullname)})"
else:
name = str(name_entry.get()) + f" ({dir_files.get(path + static_fullname)})"
new_fullname = name + formatname
else:
pass
print(dir_files)
Process(target=get_info, args=(path, new_fullname, url_entry)).start()
urllib.request.urlretrieve(url, path + new_fullname)
if len(new_fullname) > 20:
toast.show_toast(title="8-bit Downloader",
msg=f"{new_fullname[:21] + '...'} was successfully downloaded. to '{path}'"
, duration=6, threaded=True)
else:
toast.show_toast(title="8-bit Downloader", msg=f"{new_fullname} was successfully downloaded. to '{path}'"
, duration=6, threaded=True)
files_downloading -= 1
status_bar.config(text=f"Downloading {files_downloading} file(s)...")
if files_downloading == 0:
status_bar.config(text="Download(s) successful!")
if __name__ == '__main__':
root = Tk()
tabs = ttk.Notebook()
# the top menu
num = IntVar()
chum = IntVar()
var = IntVar()
toast = win10toast.ToastNotifier()
def start_download():
Process(target=download_files,
args=(status_bar, url_entry, output_entry, name_entry, format_entry, num, chum, var),
daemon=True).start()
# the status bar
status_bar = Label(main_window, text="Awaiting download...", bd=1, relief=SUNKEN, anchor=W)
status_bar.pack(side=BOTTOM, fill=X)
# the download frame
body_frame = Frame(main_window, bg="light blue")
download_button = ttk.Button(body_frame, text="Download! ", command=start_download, padding=40, style='my.TButton')
download_button_tip = CreateToolTip(download_button, "Initiates the downloading process. ")
download_button.pack(side=LEFT, pady=5, padx=5)
body_frame.pack(side=LEFT, fill=Y)
def clear_entry(entryname, variable=None):
if variable is not None:
variable.set(0)
entryname.config(state=NORMAL)
entryname.delete(0, END)
if entryname is format_entry:
entryname.insert(0, '.')
# the main interaction menu
inter_frame = Frame(main_window)
trash_icon = ImageTk.PhotoImage(Image.open("icons/Asset 6.png"))
settings_icon = ImageTk.PhotoImage(Image.open("icons/Settings-icon.png"))
add_icon = ImageTk.PhotoImage(Image.open("icons/Plus-icon-8.png"))
minus_icon = ImageTk.PhotoImage(Image.open("icons/Minus-icon-8.png"))
change_path_icon = ImageTk.PhotoImage(Image.open("icons/Change-icon-8.png"))
url_entry = ttk.Entry(inter_frame, width=30)
label = ttk.Label(inter_frame, text="Enter the image URL: ")
clr_url = ttk.Button(inter_frame, image=trash_icon, command=lambda: clear_entry(url_entry))
file_format = ttk.Label(inter_frame, text="Choose your file format: ")
format_entry = ttk.Entry(inter_frame, width=30)
clr_format = ttk.Button(inter_frame, image=trash_icon, command=lambda: clear_entry(format_entry, var))
file_name = ttk.Label(inter_frame, text="File's name: ")
name_entry = ttk.Entry(inter_frame, width=30)
clr_name = ttk.Button(inter_frame, image=trash_icon, command=lambda: clear_entry(name_entry, num))
check_name_manual = ttk.Radiobutton(inter_frame, text="Enter name manually", variable=num,
value=0, command=lambda: name_entry.config(state=NORMAL))
check_name_auto = ttk.Radiobutton(inter_frame, text="Download with default name", variable=num,
value=1, command=lambda: name_entry.config(state=DISABLED))
check_format_manual = ttk.Radiobutton(inter_frame, text="Enter format manually", variable=var,
value=0, command=lambda: format_entry.config(state=NORMAL))
check_format_auto = ttk.Radiobutton(inter_frame, text="Download with default format", variable=var,
value=1, command=lambda: format_entry.config(state=DISABLED))
output_path = ttk.Label(inter_frame, text="Choose output path: ")
output_entry = ttk.Entry(inter_frame, width=30)
def set_path():
directory = filedialog.askdirectory(initialdir="/Downloads", title="Choose path")
if directory:
output_entry.delete(0, END)
output_entry.insert(0, directory)
select_path_btn = ttk.Button(inter_frame, width=3, text="...", command=set_path)
select_path_btn_tip = CreateToolTip(select_path_btn, "Pops up a filedialog to change directory. ")
default_path_btn = ttk.Button(inter_frame, image=settings_icon, command=None)
check_default_manual = ttk.Radiobutton(inter_frame, text="Enter path manually", variable=chum,
value=0, command=lambda: output_entry.config(state=NORMAL))
check_default_auto = ttk.Radiobutton(inter_frame, text="Download to default path", variable=chum,
value=1, command=lambda: output_entry.config(state=DISABLED))
file_name.grid(row=0, column=0, pady=(15, 10))
name_entry.grid(row=0, column=1, pady=(15, 10))
clr_name.grid(row=0, column=2, pady=(5, 0))
check_name_manual.grid(row=1, column=0, padx=(10, 0))
check_name_auto.grid(row=1, column=1, padx=(10, 0))
label.grid(row=2, column=0, pady=10, padx=(10, 0))
url_entry.grid(row=2, column=1, pady=10, padx=(10, 0))
clr_url.grid(row=2, column=2)
file_format.grid(row=3, column=0, pady=10, padx=(10, 0))
format_entry.grid(row=3, column=1, pady=10, padx=(10, 0))
format_entry.insert(0, '.')
clr_format.grid(row=3, column=2)
check_format_manual.grid(row=4, column=0, padx=(10, 0))
check_format_auto.grid(row=4, column=1, padx=(10, 0))
output_path.grid(row=5, column=0, pady=10, padx=(10, 0))
output_entry.grid(row=5, column=1, padx=(10, 5))
select_path_btn.grid(row=5, column=2)
check_default_manual.grid(row=6, column=0, pady=(0, 10), padx=(10, 0))
check_default_auto.grid(row=6, column=1, pady=(0, 10), padx=(10, 0))
default_path_btn.grid(row=6, column=2, pady=(0, 5))
inter_frame.pack(expand=1)
main_window.pack(fill="both", expand=1)
# The Downloads tab (this part is irrelevant so I wouldn't bother checking this part out just put it there in case)
lbl_await = ttk.Label(download_fr, text="Awaiting Download...", font=("Helvetica", 24))
prg_br = ttk.Progressbar(download_fr, orient=HORIZONTAL, length=250, mode='indeterminate')
my_canvas = Canvas(download_fr)
my_scrollbar = ttk.Scrollbar(download_fr, orient=VERTICAL, command=my_canvas.yview)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
lbl_await.pack(pady=(85, 8))
prg_br.pack()
prg_br.start(6)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
download_fr.pack(fill="both", expand=1)
second_frame = Frame(my_canvas)
# Add that new frame to a window in the canvas
my_canvas.create_window(0, 0, window=second_frame, anchor='nw')
# update canvas scrollregion whenever the size of second_frame is changed
second_frame.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
tabs.pack(fill="both")
tabs.add(main_window, text="Main Window")
tabs.add(download_fr, text="Downloads")
root.mainloop()
# the end!
最佳答案
我认为你的主要问题是:
TypeError: cannot pickle '_tkinter.tkapp' object
看起来您正在尝试在进程之间传递 Tk 对象。我怀疑这是否会奏效。
关于python - 为什么我收到 EOFError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64642811/
我有一个静态类。 static class AppDirectory { public static string PACSTEMP = Path.Combine(Path.GetTempPa
我已经设置了一个启用了推送通知的 iOS 应用。 我可以将消息推送到应用程序,例如角标(Badge)计数工作并相应更新。 但我从未在锁屏或其他地方看到标准的推送通知弹出窗口,但手机会振动,因此消息会通
我们有一个带有 Web 应用程序和一堆 Windows 服务的系统,它们在做一些后台工作。 每当我们需要对系统进行更实质性的更改时,我们最终不得不发出 IIS 重置,然后手动重新启动所有相关的 Win
我有以下几行 John SMith: A Pedro Smith: B Jonathan B: A John B: B Luis Diaz: A Scarlet Diaz: B 我需要获得所有获得
我正在编写一个 Java 客户端(在 weblogic 10.3 上)来调用一个安全的网络服务。我已获得安装在 cacerts、DemoIdentity.jks 和 DemoTrust,jks 中的客
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎偏离主题,因为它缺乏足够的信息来诊断问题。 更详细地描述您的问题或 include a mini
我正在尝试调用void方法addToList,该方法将通过用户传递给它的两个字符串除外。我检查了dataSource类,以确保它确实接受了那些作为参数。问题是我在该方法调用上始终收到标识符>预期错误,
我的任务:使用scanner方法从一行数据中提取字符串、 float 和整数。 数据格式为: Random String, 240.5 51603 Another String, 41.6 59087
这个问题已经有答案了: What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? (25 个回答)
首先我实例化一个游戏状态 class GameState extends state{ ArrayList levels; int currentLevelID; public GameState()
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我有一个实现为单例的 Controller 对象,它有一个可以随时驱逐对象的缓存。当一个对象即将被删除时,我想通知任何使用此 Controller 的类,以便它们能够做出适当的响应。我对这种行为的第一
因此,我尝试跨集群发送消息,该消息将包含一个 User 对象,该对象是一个可序列化类。 当我发送 String 或 int 时,它工作正常,消息发送没有问题,并且集群上的所有 channel 都收到它
我试图创建的程序是一个基本游戏,用户输入网格大小,选择 block 接收增加分数的奖品、从分数中夺走分数的强盗或结束游戏的炸弹。我收到堆栈流错误,但我不明白为什么? 抱歉,代码量很大,我只是无法找到问
使用此代码我会得到什么ConcurrentModificationException?我有一个同步(监听器)锁。 private void notifyListeners(MediumRenditio
我想在捕获 DeadlineExceededError 后正确退出。我还剩下多少钱来清理? 例如, try: do_some_work() except DeadlineExceededError
我有 2 个 Intranet 站点: http://intranetv1/ http://intranetv2/ v1基于.NET 1.1,v2基于.NET 3.5 在 v1 上,我创建了一个网页,
我有一个在 Linux 3.12 上运行的 C 程序。该程序产生几个子进程。其中一个进程会生成一个线程,该线程运行一段时间然后终止。当该子进程运行时,它会执行 epoll_wait()。 epoll_
我能够将 APNS 集成到我的应用程序中。现在我想在用户点击它或用户在使用应用程序时收到通知时处理通知。我使用下面的代码在收到通知时显示警报对话框: func application(applicat
当我试图在浏览器上运行这段代码时,出现了以下错误。"错误响应错误代码:501消息:不支持的方法(“POST”)。错误码解释:501-服务器不支持该操作。" 浏览器控制台出现以下错误: "1.加载资源失
我是一名优秀的程序员,十分优秀!