ETA(
ESTIMATED ARRIVAL) 预计到达
-
在pip中也有eta
计算公式 (v 为速度, sp 为当前进度,st 为总进度,t 为时间):
v
=
s
p
t
v=\frac {s_p} {t}
v=tsp??
p
e
r
c
e
n
t
=
s
p
s
t
?
100
%
percent = \frac {s_p} {s_t} · 100\%
percent=st?sp???100%
e
t
a
=
s
t
?
s
p
v
eta=\frac {s_t - s_p} {v}
eta=vst??sp?? eta转换为 00:00:00 的形式,当速度为0和完成时,记为 --:--:--
效果展示
stylesheet (dialog, progressBar)采用渐变 . 这是我原来做的:
import math
import os
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import ImageLoader
from functions import convert
def PaintWater(self: QtWidgets.QWidget, painter, m_offset, m_waterOffset, percent, w_color):
width, height = self.width(), self.height()
percentage = 1 - percent / 100
w = 2 * math.pi / width
A = height * m_waterOffset
k = height * percentage
water1 = QtGui.QPainterPath()
water2 = QtGui.QPainterPath()
water1.moveTo(5, height)
water2.moveTo(5, height)
if m_offset > width / 2:
m_offset = 0
for i in range(5, width - 5):
water1.lineTo(i, A * math.sin(w * i + m_offset) + k)
water2.lineTo(i, A * math.sin(w * i + m_offset + width / 2 * w) + k)
i += 1
water1.lineTo(width - 5, height)
water2.lineTo(width - 5, height)
totalpath = QtGui.QPainterPath()
totalpath.addRect(QtCore.QRectF(5, 5, width - 10, height - 10))
painter.setBrush(QtCore.Qt.gray)
painter.drawRect(self.rect())
painter.save()
painter.setPen(QtCore.Qt.NoPen)
watercolor1 = QtGui.QColor(w_color)
watercolor1.setAlpha(100)
watercolor2 = QtGui.QColor(w_color)
watercolor2.setAlpha(150)
path = totalpath.intersected(water1)
painter.setBrush(watercolor1)
painter.drawPath(path)
path = totalpath.intersected(water2)
painter.setBrush(watercolor2)
painter.drawPath(path)
painter.restore()
class WaterProgressBar(QtWidgets.QWidget):
def __init__(self, parent=None):
super(WaterProgressBar, self).__init__(parent)
self.resize(200, 60)
self.setAutoFillBackground(True)
p = QtGui.QPalette()
p.setColor(QtGui.QPalette.Background, QtCore.Qt.gray)
self.setPalette(p)
self.bg_color = QtGui.QColor("95BBFF")
self.startTimer(80)
self.m_waterOffset = 0.05
self.m_offset = 50
self.m_border_width = 10
self._percent = 90
self.finished = False
self.__reversed = 100.
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
width, height = self.width(), self.height()
if not self.finished and self._percent == 100:
self.finished = True
if not self.finished:
self.m_offset += 0.6
PaintWater(self, painter, self.m_offset, self.m_waterOffset, self._percent, self.bg_color)
elif self.__reversed > 0.:
self.__reversed -= 3.1
self.m_offset -= 0.6
painter.setBrush(QtGui.QColor(self.bg_color))
painter.drawRect(QtCore.QRectF(0, width / 100 * (100 - self.__reversed), width, height))
PaintWater(self, painter, self.m_offset, self.m_waterOffset, self.__reversed, self.bg_color)
else:
super().paintEvent(event)
m_font = QtGui.QFont()
m_font.setFamily('Microsoft YaHei')
m_font.setPixelSize(int(self.width() / 10))
painter.setPen(QtCore.Qt.white)
painter.setFont(m_font)
painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "{}%".format(self._percent))
painter.end()
class SimpleProgressDialog(QtWidgets.QDialog):
def __init__(self, parent=None, total=100):
super().__init__(parent)
self._startTime = time.time()
self._endTime = None
self._startPos = None
self._tracking = None
self._endPos = None
self.percent = 0
self.progress = 0
self.total = total
self.setObjectName("FileProgress")
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.FramelessWindowHint)
self.resize(480, 760)
font = QtGui.QFont()
font.setFamily("Consolas")
self.setFont(font)
self.horizontalLayout = QtWidgets.QHBoxLayout(self)
self.horizontalLayout.setObjectName("horizontalLayout")
self.CentralLayoutWidget = QtWidgets.QWidget(self)
self.CentralLayoutWidget.setStyleSheet("#CentralLayoutWidget {\n"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
"stop:0 rgba(82, 87, 250, 255), stop:1 rgba( "
"245, 140, 107, 255));\n "
"border-radius: 10px; border: 1px solid qlineargradient(spread:pad, "
"x1:0, y1:0, x2:1, y2:1, stop:0 rgba(82, 87, 250, 255), stop:1 rgba("
"245, 140, 107, 255));\n "
"}")
self.CentralLayoutWidget.setObjectName("CentralLayoutWidget")
self.centralLayoutWidget = QtWidgets.QVBoxLayout(self.CentralLayoutWidget)
self.centralLayoutWidget.setObjectName("centralLayoutWidget")
self.closeButton = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.closeButton.setMaximumSize(QtCore.QSize(30, 30))
self.closeButton.setBaseSize(QtCore.QSize(0, 0))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("images/close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.closeButton.setIcon(icon)
self.closeButton.setIconSize(QtCore.QSize(24, 24))
self.closeButton.setObjectName("closeButton")
self.centralLayoutWidget.addWidget(self.closeButton, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.filename_label = QtWidgets.QLabel(self.CentralLayoutWidget)
self.filename_label.setStyleSheet("color: rgb(255, 255, 255);\n"
"font: 11pt \"Consolas\";")
self.filename_label.setScaledContents(False)
self.filename_label.setObjectName("filename_label")
self.centralLayoutWidget.addWidget(self.filename_label, 0, QtCore.Qt.AlignHCenter)
self.icon_label = QtWidgets.QLabel(self.CentralLayoutWidget)
self.icon_label.setMaximumSize(QtCore.QSize(70, 70))
self.icon_label.setScaledContents(True)
self.icon_label.setObjectName("icon_label")
self.centralLayoutWidget.addWidget(self.icon_label, 0, QtCore.Qt.AlignHCenter)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.centralLayoutWidget.addItem(spacerItem)
self.fileLayout = QtWidgets.QHBoxLayout()
self.fileLayout.setObjectName("fileLayout")
self.size_label_tag = QtWidgets.QLabel()
self.size_label_tag.setObjectName("size_label")
self.size_label_tag.setStyleSheet("color: rgb(255, 255, 255);\n"
"font: 11pt \"Consolas\";")
self.fileLayout.addWidget(self.size_label_tag)
self.size_label = QtWidgets.QLabel()
self.size_label.setStyleSheet("color: rgb(255, 255, 0);\n"
"font: 11pt \"Consolas\";")
self.fileLayout.addWidget(self.size_label)
widget = QtWidgets.QWidget()
widget.setLayout(self.fileLayout)
self.centralLayoutWidget.addWidget(widget, 0, QtCore.Qt.AlignHCenter)
self.line = QtWidgets.QFrame(self.CentralLayoutWidget)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.centralLayoutWidget.addWidget(self.line)
self.infoLayout = QtWidgets.QHBoxLayout()
self.infoLayout.setObjectName("infoLayout")
self.progressLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.progressLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(83, 230, 60);")
self.progressLabel.setObjectName("progress")
self.infoLayout.addWidget(self.progressLabel)
self.speedLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.speedLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(255, 255, 0);")
self.speedLabel.setObjectName("speed")
self.infoLayout.addWidget(self.speedLabel)
self.eta = QtWidgets.QLabel(self.CentralLayoutWidget)
self.eta.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(11, 235, 255);")
self.eta.setObjectName("eta")
self.infoLayout.addWidget(self.eta)
self.centralLayoutWidget.addLayout(self.infoLayout)
self.progressbar = QtWidgets.QProgressBar(self.CentralLayoutWidget)
self.progressbar.setMinimum(0)
self.progressbar.setProperty("value", 0)
self.progressbar.setTextVisible(False)
self.progressbar.setInvertedAppearance(False)
self.progressbar.setObjectName("progressbar")
self.centralLayoutWidget.addWidget(self.progressbar)
self.percentLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.percentLabel.setStyleSheet("font: 11pt \"Consolas\";\n"
"color: rgb(0, 85, 255);")
self.percentLabel.setObjectName("percent")
self.centralLayoutWidget.addWidget(self.percentLabel, 0, QtCore.Qt.AlignHCenter)
self.openFile = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.openFile.setMaximumSize(QtCore.QSize(100, 16777215))
self.openFile.setObjectName("openFile")
self.centralLayoutWidget.addWidget(self.openFile, 0, QtCore.Qt.AlignHCenter)
self.openPath = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.openPath.setMaximumSize(QtCore.QSize(100, 16777215))
self.openPath.setObjectName("openFile_2")
self.centralLayoutWidget.addWidget(self.openPath, 0, QtCore.Qt.AlignHCenter)
self.horizontalLayout.addWidget(self.CentralLayoutWidget)
self.closeButton.clicked.connect(self.close)
QtCore.QMetaObject.connectSlotsByName(self)
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("FileProgress", "Dialog"))
self.filename_label.setText(_translate("FileProgress", "{filename}"))
self.progressLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>当前进度</p></body></html>"))
self.progressLabel.setText(_translate("FileProgress", f"0 / {convert(self.total)}"))
self.speedLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>速度</p></body></html>"))
self.speedLabel.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
self.speedLabel.setText(_translate("FileProgress", "speed"))
self.eta.setToolTip(_translate("FileProgress",
"<html><head/><body><p><span style=\" font-weight:600; "
"color:#ff0000;\">eta</span><span style=\" color:#000000;\">, 即</span><span "
"style=\" font-weight:600; color:#000000;\">E</span><span style=\" "
"color:#000000;\">stimated </span><span style=\" font-weight:600; "
"color:#000000;\">T</span><span style=\" color:#000000;\">ime of </span><span "
"style=\" font-weight:600; color:#000000;\">A</span><span style=\" "
"color:#000000;\">rrival, </span><span style=\" font-weight:600; "
"color:#000000;\">预计到达时间</span><span style=\" "
"color:#000000;\">.</span></p></body></html>"))
self.eta.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
self.eta.setText(_translate("FileProgress", "eta"))
self.percentLabel.setText(_translate("FileProgress", "0%"))
self.openFile.setText(_translate("FileProgress", "打开文件"))
self.openPath.setText(_translate("FileProgress", "转到目录"))
self.size_label_tag.setText(_translate("FileProgress", "大小:"))
self.size_label.setText(_translate("FileProgress", f"{convert(self.total)}"))
self.progressbar.setRange(0, 0)
self.setWindowOpacity(0.9)
self.progressbar.setStyleSheet("\n"
"#progressbar {\n"
" min-height: 12px;\n"
" max-height: 12px;\n"
" border-radius: 6px;\n"
"}\n"
"#progressbar::chunk {\n"
" border-radius: 6px;\n"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
f"stop:0 rgba(50, 0, 255, 255), stop:1 rgba({self.percent}, 185, 255, 255));\n "
"}")
self.openFile.setEnabled(False)
def _set_eta(self, _stamp: (int, float)):
if self.is_finished():
if not isinstance(self._endTime, (int, float)):
self._endTime = time.time()
self.eta.setText("total " + str(time.strftime("%H:%M:%S",
time.gmtime(float(self._endTime - self._startTime)))))
else:
if _stamp == 0:
self.eta.setText("eta --:--:--")
else:
self.eta.setText("eta " + str(time.strftime("%H:%M:%S", time.gmtime(float(_stamp)))))
def _set_speed(self, _transfer: int):
self.speedLabel.setText(f"{'total ' if self.is_finished() else str()}{convert(_transfer)}/s")
def _set_progress(self):
if self.is_finished():
self.progressLabel.setText("finished")
else:
self.progressLabel.setText(f"{convert(self.progress)} / {convert(self.total)}")
def mouseMoveEvent(self, e):
if self._tracking:
self._endPos = e.pos() - self._startPos
self.move(self.pos() + self._endPos)
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
self._startPos = QtCore.QPoint(e.x(), e.y())
self._tracking = True
def mouseReleaseEvent(self, e):
if e.button() == Qt.LeftButton:
self._tracking = False
self._startPos = None
self._endPos = None
@QtCore.pyqtSlot(int)
def updateValue(self, length=1):
self.progress += length
if self.progress > self.total:
self.progress = self.total
self.percent = int(round(self.progress / self.total, 2) * 100)
if self.is_finished():
self.openFile.setEnabled(True)
self.progressbar.hide()
self.percentLabel.hide()
self.progressbar.setMaximum(100)
self.progressbar.setValue(self.percent)
self.percentLabel.setText(f"{self.percent}%")
self.valueChangedEvent(length)
self._set_progress()
def is_finished(self) -> bool:
return self.progress == self.total
def valueChangedEvent(self, added):
pass
class ProgressDialog(SimpleProgressDialog):
def __init__(self, total, filename, filepath, time_stamp=None, progress=None, parent=None, x=0, y=0):
super(ProgressDialog, self).__init__(parent, total=total)
self.resize(320, 640)
self.timeStamp = time.time()
self.eta_value = 0
self.speed = 0
self.filename = filename
self.filepath = filepath
self.file = os.path.join(filepath, filename)
self.eta_added_value = 0
self.icon_label.setPixmap(QtGui.QPixmap(ImageLoader.get(filename)))
self.filename_label.setText(filename)
self.openFile.clicked.connect(self.startFile)
self.openPath.clicked.connect(self.startPath)
self.count_eta_timer = QtCore.QTimer(self)
self.count_eta_timer.timeout.connect(self.update)
self.count_eta_timer.start(500)
self.update()
if isinstance(progress, int) and isinstance(progress, (int, float)):
self.already_start(progress, time_stamp)
self.exec_()
def already_start(self, progress: int, time_stamp: (int, float)):
self.progress = progress
self._startTime = time_stamp
def valueChangedEvent(self, added):
self.eta_added_value += added
def startFile(self, *args):
if os.path.isfile(self.file):
os.startfile(self.file)
def startPath(self, *args):
if os.path.isfile(self.filepath):
os.startfile(self.filepath)
def update(self, *args):
super().update(*args)
self._set_eta(self.eta_value)
self._set_speed(self.speed)
if not self.is_finished():
self.speed = self.eta_added_value / (
time.time() - self.timeStamp) if time.time() - self.timeStamp != 0 else 0
self.eta_value = (self.total - self.progress) / self.speed if self.speed != 0 else 0
self.timeStamp = time.time()
else:
self.speed = self.total / (self._endTime - self._startTime)
self.eta_added_value = 0
class FileListWidget(QtWidgets.QListWidget):
class ListWidgetLayout(QtWidgets.QWidget):
def __init__(self, name, total, size, parent=None):
super(FileListWidget.ListWidgetLayout, self).__init__(parent)
self.size = size
self.total = total
self.segment = math.ceil(self.size // self.total)
self.progress = 0
hbox = QtWidgets.QHBoxLayout(self)
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(QtWidgets.QLabel(name + f"\n({convert(self.size)})", self))
progress = QtWidgets.QProgressBar()
progress.setMaximum(total)
progress.setStyleSheet("QProgressBar{\n"
"text-align: center;\n"
'font: 9pt "Consolas";\n'
"}")
vbox.setObjectName("name, speed Info")
hbox.setObjectName("Info and Progress")
progress.setTextVisible(True)
progress.setRange(0, 0)
self.label = QtWidgets.QLabel(self)
self.label.setStyleSheet("color: rgb(60, 112, 255);")
vbox.addWidget(self.label)
self.progressbar = progress
vbox.setSpacing(2)
hbox.addLayout(vbox)
hbox.addWidget(progress)
self.setLayout(hbox)
fonts = QtGui.QFont()
fonts.setFamily("Consolas")
fonts.setPointSize(9)
self.setFont(fonts)
self.label.setFont(fonts)
self.start_time = time.time()
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.timers)
self.timer.start(50)
def timers(self, *args) -> None:
timeit = self.get_time()
if timeit == 0:
return
content = f"{convert(int((self.segment * self.progress) / timeit))}/s ({self.str_time()} 秒)"
self.label.setText(content)
def get_progressbar(self) -> QtWidgets.QProgressBar:
return self.progressbar
def is_finished(self) -> bool:
return bool(self.progress >= self.total)
def update(self) -> None:
if self.progress == 0:
self.progressbar.setMaximum(self.total)
if self.is_finished():
return
self.progress += 1
if self.is_finished():
self.end_time = time.time()
self.progressbar.setValue(self.progress)
def get_total(self) -> int:
return self.total
def get_time(self) -> float:
return getattr(self, "end_time", time.time()) - self.start_time
def str_time(self) -> str:
return "%0.1f" % (self.get_time())
def get_progress(self) -> int:
return self.progress
class ListItem(QtWidgets.QListWidgetItem):
def __init__(self, parent: QtWidgets.QListWidget, icon: QtGui.QIcon, index: int, layout, size=(200, 80)):
super(FileListWidget.ListItem, self).__init__(icon, str(), parent)
self.index_name = index
self.setSizeHint(QtCore.QSize(200, 80))
self.setSizeHint(QtCore.QSize(*size))
parent.addItem(self)
parent.setItemWidget(self, layout)
DOWNLOAD = 0
UPLOAD = 1
def __init__(self, _save_path, parent=None):
self.x, self.y = 0, 0
self.dialog_index = 0
self.dialog = None
self.rightClickedItem = None
self.path = None
self.fpath = None
self.current = ""
super().__init__(parent)
self.setWindowIcon(QtGui.QIcon("images/file.png"))
self.download = QtGui.QIcon("images/download.png")
self.upload = QtGui.QIcon("images/upload.png")
self.LOAD_dict = {self.DOWNLOAD: self.download,
self.UPLOAD: self.upload}
self.save_path = _save_path
self.filedict = {}
self.pathdict = {}
self.namedict = {}
self.infodict = {}
self.setObjectName("FileDisplayWindow")
self.resize(666, 421)
font = QtGui.QFont()
font.setFamily("Consolas")
self.setFont(font)
self.setWindowTitle(QtCore.QCoreApplication.translate("Dialog", "Files"))
self.itemClicked.connect(self.fileClicked)
self.menu = QtWidgets.QMenu(self)
open_file = QtWidgets.QAction(QtGui.QIcon("images/file.png"), '打开文件', self)
open_file.triggered.connect(self.startfile)
self.menu.addAction(open_file)
open_path = QtWidgets.QAction(QtGui.QIcon("images/folder.png"), '打开文件夹', self)
open_path.triggered.connect(self.startpath)
self.menu.addAction(open_path)
QtCore.QMetaObject.connectSlotsByName(self)
def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
super().mousePressEvent(event)
if event.button() == QtCore.Qt.RightButton and self.itemAt(event.pos()):
item = self.itemAt(event.pos())
index: int = item.index_name
self.fpath = self.pathdict[index]
self.path = os.path.dirname(self.fpath)
self.menu.exec(event.globalPos())
@QtCore.pyqtSlot(str, int, int, tuple)
def new_file(self, name, total, size, info):
self.activateWindow()
index = len(self.filedict)
_type, localfile = info
layout = FileListWidget.ListWidgetLayout(name, total, size)
self.filedict[index] = (layout, size)
self.pathdict[index] = localfile
self.infodict[index] = (total, name, os.path.dirname(localfile), time.time())
item = FileListWidget.ListItem(self, self.LOAD_dict.get(_type, self.UPLOAD), index, layout)
self.show()
@QtCore.pyqtSlot(int)
def update_file(self, index: int):
layout, size = self.filedict[index]
layout: FileListWidget.ListWidgetLayout
layout.update()
if isinstance(self.dialog, ProgressDialog):
if index == self.dialog_index:
self.dialog.updateValue(1)
def fileClicked(self, item: ListItem):
index = item.index_name
self.dialog = ProgressDialog(*self.infodict[index], self.filedict[index][0].get_progress())
self.dialog_index = index
def startfile(self, *args):
if isinstance(self.fpath, str) and os.path.isfile(self.fpath):
os.startfile(self.fpath)
def startpath(self, *args):
if isinstance(self.path, str) and os.path.isdir(self.path):
os.startfile(self.path)
def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
super(FileListWidget, self).mouseMoveEvent(event)
self.x, self.y = event.x(), event.y()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
a = FileListWidget(os.path.join(os.path.dirname(os.path.realpath(__file__)), "database", "resource"))
a.new_file("asdf", 1010, 11111, (0, "C:/users/zhnwe/desktop/1.rte"))
a.show()
app.exec_()
现在呢,我有创建了一个类_cSpeed , 方便在3个类中管理.
class _cSpeed(object):
def __init__(self, total: (int, float) = 100, slot: (QtCore.pyqtSlot, None) = None):
self.__create_time = time.time()
self.__end_time = None
self.__update_value = int()
self.__total_value = total
self.slots = []
self.add_slot(slot)
self.timed_once = time.time()
self.update_once = int()
def add_slot(self, slot: QtCore.pyqtSlot):
if callable(slot):
self.slots.append(slot)
def get_total(self) -> str:
return convert(self.__total_value)
def _count_speed(self) -> float:
resp = self.update_once / (time.time() - self.timed_once) if (time.time() - self.timed_once) else 0.
self.update_once = int()
self.timed_once = time.time()
return resp
def _round_speed(self, value: int = 2) -> float:
return round(self._count_speed(), value)
def get_speed(self, value: int = 2, exact=False) -> str:
return f"{convert(self._round_speed(value), bool(exact))}/s"
def get_percent(self) -> int:
return int(round(self.__update_value / self.__total_value, 2) * 100)
def update_value(self, value: (int, float) = 1.) -> None:
self.__update_value += value
self.update_once += value
if self.__update_value >= self.__total_value:
self.__update_value = self.__total_value
if self.__end_time is None:
self.__end_time = time.time()
for slot in self.slots:
slot()
def _value(self) -> (float, int):
return self.__update_value
def is_finished(self) -> bool:
return not bool(self._get_over())
def get_progress(self) -> str:
return f"{convert(self.__update_value)} / {convert(self.__total_value)}" \
if self._get_over() else convert(self.__total_value)
def _get_over(self) -> float:
return self.__total_value - self.__update_value
def get_eta(self) -> str:
assert isinstance(self.__total_value, (int, float)), "total value is Incalculable!"
return f'eta {time.strftime("%H:%M:%S", time.gmtime(self._get_over() / self._count_speed())) if self._count_speed() else "--:--:--"}' \
if self._get_over() else \
f'total {time.strftime("%H:%M:%S", time.gmtime(self.__end_time - self.__create_time))}'
def _get_time(self) -> float:
return (self.__end_time if isinstance(self.__end_time, float) else time.time()) - self.__create_time
全部代码
import math
import os
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import ImageLoader
from functions import convert
class _cSpeed(object):
def __init__(self, total: (int, float) = 100, slot: (QtCore.pyqtSlot, None) = None):
self.__create_time = time.time()
self.__end_time = None
self.__update_value = int()
self.__total_value = total
self.slots = []
self.add_slot(slot)
self.timed_once = time.time()
self.update_once = int()
def add_slot(self, slot: QtCore.pyqtSlot):
if callable(slot):
self.slots.append(slot)
def get_total(self) -> str:
return convert(self.__total_value)
def _count_speed(self) -> float:
resp = self.update_once / (time.time() - self.timed_once) if (time.time() - self.timed_once) else 0.
self.update_once = int()
self.timed_once = time.time()
return resp
def _round_speed(self, value: int = 2) -> float:
return round(self._count_speed(), value)
def get_speed(self, value: int = 2, exact=False) -> str:
return f"{convert(self._round_speed(value), bool(exact))}/s"
def get_percent(self) -> int:
return int(round(self.__update_value / self.__total_value, 2) * 100)
def update_value(self, value: (int, float) = 1.) -> None:
self.__update_value += value
self.update_once += value
if self.__update_value >= self.__total_value:
self.__update_value = self.__total_value
if self.__end_time is None:
self.__end_time = time.time()
for slot in self.slots:
slot()
def _value(self) -> (float, int):
return self.__update_value
def is_finished(self) -> bool:
return not bool(self._get_over())
def get_progress(self) -> str:
return f"{convert(self.__update_value)} / {convert(self.__total_value)}" \
if self._get_over() else convert(self.__total_value)
def _get_over(self) -> float:
return self.__total_value - self.__update_value
def get_eta(self) -> str:
assert isinstance(self.__total_value, (int, float)), "total value is Incalculable!"
return f'eta {time.strftime("%H:%M:%S", time.gmtime(self._get_over() / self._count_speed())) if self._count_speed() else "--:--:--"}' \
if self._get_over() else \
f'total {time.strftime("%H:%M:%S", time.gmtime(self.__end_time - self.__create_time))}'
def _get_time(self) -> float:
return (self.__end_time if isinstance(self.__end_time, float) else time.time()) - self.__create_time
class WaterProgressBar(QtWidgets.QWidget):
def PaintWater(self: QtWidgets.QWidget, painter, m_offset, m_waterOffset, percent, w_color):
width, height = self.width(), self.height()
percentage = 1 - percent / 100
w = 2 * math.pi / width
A = height * m_waterOffset
k = height * percentage
water1 = QtGui.QPainterPath()
water2 = QtGui.QPainterPath()
water1.moveTo(5, height)
water2.moveTo(5, height)
if m_offset > width / 2:
m_offset = 0
for i in range(5, width - 5):
water1.lineTo(i, A * math.sin(w * i + m_offset) + k)
water2.lineTo(i, A * math.sin(w * i + m_offset + width / 2 * w) + k)
i += 1
water1.lineTo(width - 5, height)
water2.lineTo(width - 5, height)
total_path = QtGui.QPainterPath()
total_path.addRect(QtCore.QRectF(5, 5, width - 10, height - 10))
painter.setBrush(QtCore.Qt.gray)
painter.drawRect(self.rect())
painter.save()
painter.setPen(QtCore.Qt.NoPen)
watercolor1 = QtGui.QColor(w_color)
watercolor1.setAlpha(100)
watercolor2 = QtGui.QColor(w_color)
watercolor2.setAlpha(150)
path = total_path.intersected(water1)
painter.setBrush(watercolor1)
painter.drawPath(path)
path = total_path.intersected(water2)
painter.setBrush(watercolor2)
painter.drawPath(path)
painter.restore()
def __init__(self, parent=None):
super(WaterProgressBar, self).__init__(parent)
self.resize(200, 60)
self.setAutoFillBackground(True)
p = QtGui.QPalette()
p.setColor(QtGui.QPalette.Background, QtCore.Qt.gray)
self.setPalette(p)
self.bg_color = QtGui.QColor("95BBFF")
self.startTimer(80)
self.m_waterOffset = 0.05
self.m_offset = 50
self.m_border_width = 10
self._percent = 90
self.finished = False
self.__reversed = 100.
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
width, height = self.width(), self.height()
if not self.finished and self._percent == 100:
self.finished = True
if not self.finished:
self.m_offset += 0.6
self.PaintWater(self, painter, self.m_offset, self.m_waterOffset, self._percent, self.bg_color)
elif self.__reversed > 0.:
self.__reversed -= 3.1
self.m_offset -= 0.6
painter.setBrush(QtGui.QColor(self.bg_color))
painter.drawRect(QtCore.QRectF(0, width / 100 * (100 - self.__reversed), width, height))
self.PaintWater(self, painter, self.m_offset, self.m_waterOffset, self.__reversed, self.bg_color)
else:
super().paintEvent(event)
m_font = QtGui.QFont()
m_font.setFamily('Microsoft YaHei')
m_font.setPixelSize(int(self.width() / 10))
painter.setPen(QtCore.Qt.white)
painter.setFont(m_font)
painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "{}%".format(self._percent))
painter.end()
class SimpleProgressDialog(QtWidgets.QDialog):
def __init__(self, parent=None, cSpeed: _cSpeed = _cSpeed(100)):
super().__init__(parent)
self._startPos = None
self._tracking = None
self._endPos = None
self.percent = 0
self._cSpeed = cSpeed
self.setObjectName("FileProgress")
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.FramelessWindowHint)
self.resize(480, 760)
font = QtGui.QFont()
font.setFamily("Consolas")
self.setFont(font)
self.horizontalLayout = QtWidgets.QHBoxLayout(self)
self.horizontalLayout.setObjectName("horizontalLayout")
self.CentralLayoutWidget = QtWidgets.QWidget(self)
self.CentralLayoutWidget.setStyleSheet("#CentralLayoutWidget {\n"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
"stop:0 rgba(82, 87, 250, 255), stop:1 rgba( "
"245, 140, 107, 255));\n "
"border-radius: 10px; border: 1px solid qlineargradient(spread:pad, "
"x1:0, y1:0, x2:1, y2:1, stop:0 rgba(82, 87, 250, 255), stop:1 rgba("
"245, 140, 107, 255));\n "
"}")
self.CentralLayoutWidget.setObjectName("CentralLayoutWidget")
self.centralLayoutWidget = QtWidgets.QVBoxLayout(self.CentralLayoutWidget)
self.centralLayoutWidget.setObjectName("centralLayoutWidget")
self.closeButton = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.closeButton.setMaximumSize(QtCore.QSize(30, 30))
self.closeButton.setBaseSize(QtCore.QSize(0, 0))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("images/close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.closeButton.setIcon(icon)
self.closeButton.setIconSize(QtCore.QSize(24, 24))
self.closeButton.setObjectName("closeButton")
self.centralLayoutWidget.addWidget(self.closeButton, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.filename_label = QtWidgets.QLabel(self.CentralLayoutWidget)
self.filename_label.setStyleSheet("color: rgb(255, 255, 255);\n"
"font: 11pt \"Consolas\";")
self.filename_label.setScaledContents(False)
self.filename_label.setObjectName("filename_label")
self.centralLayoutWidget.addWidget(self.filename_label, 0, QtCore.Qt.AlignHCenter)
self.icon_label = QtWidgets.QLabel(self.CentralLayoutWidget)
self.icon_label.setMaximumSize(QtCore.QSize(70, 70))
self.icon_label.setScaledContents(True)
self.icon_label.setObjectName("icon_label")
self.centralLayoutWidget.addWidget(self.icon_label, 0, QtCore.Qt.AlignHCenter)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.centralLayoutWidget.addItem(spacerItem)
self.fileLayout = QtWidgets.QHBoxLayout()
self.fileLayout.setObjectName("fileLayout")
self.size_label_tag = QtWidgets.QLabel()
self.size_label_tag.setObjectName("size_label")
self.size_label_tag.setStyleSheet("color: rgb(255, 255, 255);\n"
"font: 11pt \"Consolas\";")
self.fileLayout.addWidget(self.size_label_tag)
self.size_label = QtWidgets.QLabel()
self.size_label.setStyleSheet("color: rgb(255, 255, 0);\n"
"font: 11pt \"Consolas\";")
self.fileLayout.addWidget(self.size_label)
widget = QtWidgets.QWidget()
widget.setLayout(self.fileLayout)
self.centralLayoutWidget.addWidget(widget, 0, QtCore.Qt.AlignHCenter)
self.line = QtWidgets.QFrame(self.CentralLayoutWidget)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.centralLayoutWidget.addWidget(self.line)
self.infoLayout = QtWidgets.QHBoxLayout()
self.infoLayout.setObjectName("infoLayout")
self.progressLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.progressLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(83, 230, 60);")
self.progressLabel.setObjectName("progress")
self.infoLayout.addWidget(self.progressLabel)
self.speedLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.speedLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(255, 255, 0);")
self.speedLabel.setObjectName("speed")
self.infoLayout.addWidget(self.speedLabel)
self.eta = QtWidgets.QLabel(self.CentralLayoutWidget)
self.eta.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
"color: rgb(11, 235, 255);")
self.eta.setObjectName("eta")
self.infoLayout.addWidget(self.eta)
self.centralLayoutWidget.addLayout(self.infoLayout)
self.progressbar = QtWidgets.QProgressBar(self.CentralLayoutWidget)
self.progressbar.setMinimum(0)
self.progressbar.setProperty("value", 0)
self.progressbar.setTextVisible(False)
self.progressbar.setInvertedAppearance(False)
self.progressbar.setObjectName("progressbar")
self.centralLayoutWidget.addWidget(self.progressbar)
self.percentLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
self.percentLabel.setStyleSheet("font: 11pt \"Consolas\";\n"
"color: rgb(0, 85, 255);")
self.percentLabel.setObjectName("percent")
self.centralLayoutWidget.addWidget(self.percentLabel, 0, QtCore.Qt.AlignHCenter)
self.openFile = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.openFile.setMaximumSize(QtCore.QSize(100, 16777215))
self.openFile.setObjectName("openFile")
self.centralLayoutWidget.addWidget(self.openFile, 0, QtCore.Qt.AlignHCenter)
self.openPath = QtWidgets.QPushButton(self.CentralLayoutWidget)
self.openPath.setMaximumSize(QtCore.QSize(100, 16777215))
self.openPath.setObjectName("openFile_2")
self.centralLayoutWidget.addWidget(self.openPath, 0, QtCore.Qt.AlignHCenter)
self.horizontalLayout.addWidget(self.CentralLayoutWidget)
self.closeButton.clicked.connect(self.close)
QtCore.QMetaObject.connectSlotsByName(self)
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("FileProgress", "Dialog"))
self.filename_label.setText(_translate("FileProgress", "{filename}"))
self.progressLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>当前进度</p></body></html>"))
self.progressLabel.setText(_translate("FileProgress", f") / {self._cSpeed.get_total()}"))
self.speedLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>速度</p></body></html>"))
self.speedLabel.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
self.speedLabel.setText(_translate("FileProgress", "speed"))
self.eta.setToolTip(_translate("FileProgress",
"<html><head/><body><p><span style=\" font-weight:600; "
"color:#ff0000;\">eta</span><span style=\" color:#000000;\">, 即</span><span "
"style=\" font-weight:600; color:#000000;\">E</span><span style=\" "
"color:#000000;\">stimated </span><span style=\" font-weight:600; "
"color:#000000;\">T</span><span style=\" color:#000000;\">ime of </span><span "
"style=\" font-weight:600; color:#000000;\">A</span><span style=\" "
"color:#000000;\">rrival, </span><span style=\" font-weight:600; "
"color:#000000;\">预计到达时间</span><span style=\" "
"color:#000000;\">.</span></p></body></html>"))
self.eta.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
self.eta.setText(_translate("FileProgress", "eta"))
self.percentLabel.setText(_translate("FileProgress", "0%"))
self.openFile.setText(_translate("FileProgress", "打开文件"))
self.openPath.setText(_translate("FileProgress", "转到目录"))
self.size_label_tag.setText(_translate("FileProgress", "大小:"))
self.size_label.setText(_translate("FileProgress", self._cSpeed.get_total()))
self.progressbar.setRange(0, 0)
self.setWindowOpacity(0.9)
self.progressbar.setStyleSheet("\n"
"#progressbar {\n"
" min-height: 12px;\n"
" max-height: 12px;\n"
" border-radius: 6px;\n"
"}\n"
"#progressbar::chunk {\n"
" border-radius: 6px;\n"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
f"stop:0 rgba(50, 0, 255, 255), stop:1 rgba({self._cSpeed.get_percent()}, 185, "
f"255, 255));\n "
"}")
self.openFile.setEnabled(False)
self._cSpeed.add_slot(self.updateValue)
def _set_eta(self):
"""
def _set_eta(self, _stamp: (int, float)):
if self.is_finished():
if not isinstance(self._endTime, (int, float)):
self._endTime = time.time()
self.eta.setText("total " + str(time.strftime("%H:%M:%S",
time.gmtime(float(self._endTime - self._startTime)))))
else:
if _stamp == 0:
self.eta.setText("eta --:--:--")
else:
self.eta.setText("eta " + str(time.strftime("%H:%M:%S", time.gmtime(float(_stamp)))))
"""
self.eta.setText(self._cSpeed.get_eta())
def _set_speed(self):
"""
def _set_speed(self, _transfer: int):
self.speedLabel.setText(f"{'total ' if self.is_finished() else str()}{convert(_transfer)}/s")
"""
self.speedLabel.setText(self._cSpeed.get_speed())
def _set_progress(self):
"""
def _set_progress(self):
if self.is_finished():
self.progressLabel.setText("finished")
else:
self.progressLabel.setText(f"{convert(self.progress)} / {convert(self.total)}")
"""
self.progressLabel.setText(self._cSpeed.get_progress())
def mouseMoveEvent(self, e):
if self._tracking:
self._endPos = e.pos() - self._startPos
self.move(self.pos() + self._endPos)
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
self._startPos = QtCore.QPoint(e.x(), e.y())
self._tracking = True
def mouseReleaseEvent(self, e):
if e.button() == Qt.LeftButton:
self._tracking = False
self._startPos = None
self._endPos = None
@QtCore.pyqtSlot()
def updateValue(self):
self.percent = self._cSpeed.get_percent()
if self._cSpeed.is_finished():
self.openFile.setEnabled(True)
self.progressbar.hide()
self.percentLabel.hide()
if self._cSpeed.get_percent() > 0:
self.progressbar.setMaximum(100)
self.progressbar.setValue(self.percent)
self.percentLabel.setText(f"{self.percent}%")
self._set_speed()
self._set_eta()
self._set_progress()
class ProgressDialog(SimpleProgressDialog):
def __init__(self, _cSpeed, filename, filepath, parent=None):
super(ProgressDialog, self).__init__(parent, cSpeed=_cSpeed)
self.resize(320, 640)
self.filename = filename
self.filepath = filepath
self.file = os.path.join(filepath, filename)
self.icon_label.setPixmap(QtGui.QPixmap(ImageLoader.get(filename)))
self.filename_label.setText(filename)
self.openFile.clicked.connect(self.startFile)
self.openPath.clicked.connect(self.startPath)
self.updateValue()
self.startTimer(500)
self.exec_()
def startFile(self, *args):
if os.path.isfile(self.file):
os.startfile(self.file)
def timerEvent(self, a0: QtCore.QTimerEvent) -> None:
self.updateValue()
def startPath(self, *args):
if os.path.isfile(self.filepath):
os.startfile(self.filepath)
class FileListWidget(QtWidgets.QListWidget):
class ListWidgetLayout(QtWidgets.QWidget):
def __init__(self, name, cSpeed: _cSpeed = _cSpeed(100), parent=None):
super(FileListWidget.ListWidgetLayout, self).__init__(parent)
self._cSpeed = cSpeed
hbox = QtWidgets.QHBoxLayout(self)
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(QtWidgets.QLabel(name + f"\n({self._cSpeed.get_total()})", self))
progress = QtWidgets.QProgressBar()
progress.setMaximum(100)
progress.setStyleSheet("QProgressBar{\n"
"text-align: center;\n"
'font: 9pt "Consolas";\n'
"}")
vbox.setObjectName("name, speed Info")
hbox.setObjectName("Info and Progress")
progress.setTextVisible(True)
progress.setRange(0, 0)
self.eta_label = QtWidgets.QLabel(self)
self.eta_label.setStyleSheet("color: rgb(60, 112, 255);")
vbox.addWidget(self.eta_label)
self.progressbar = progress
vbox.setSpacing(2)
hbox.addLayout(vbox)
hbox.addWidget(progress)
self.setLayout(hbox)
fonts = QtGui.QFont()
fonts.setFamily("Consolas")
fonts.setPointSize(9)
self.setFont(fonts)
self.eta_label.setFont(fonts)
self.start_time = time.time()
self._cSpeed.add_slot(self.updateValue)
self.startTimer(100)
def timerEvent(self, a0: QtCore.QTimerEvent) -> None:
self.eta_label.setText(f"{self._cSpeed.get_speed()} ({self._cSpeed.get_eta()})")
@QtCore.pyqtSlot()
def updateValue(self) -> None:
if self._cSpeed.get_percent() > 0:
self.progressbar.setMaximum(100)
self.progressbar.setValue(self._cSpeed.get_percent())
class ListItem(QtWidgets.QListWidgetItem):
def __init__(self, parent: QtWidgets.QListWidget, icon: QtGui.QIcon, index: int, layout, size=(200, 100)):
super(FileListWidget.ListItem, self).__init__(icon, str(), parent)
self.index_name = index
self.setSizeHint(QtCore.QSize(*size))
self.setSizeHint(QtCore.QSize(*size))
parent.addItem(self)
parent.setItemWidget(self, layout)
DOWNLOAD = 0
UPLOAD = 1
def __init__(self, _save_path, parent=None):
self.x, self.y = 0, 0
self.dialog_index = 0
self.dialog = None
self.rightClickedItem = None
self.path = None
self.fpath = None
self.current = ""
super().__init__(parent)
self.setWindowIcon(QtGui.QIcon("images/file.png"))
self.download = QtGui.QIcon("images/download.png")
self.upload = QtGui.QIcon("images/upload.png")
self.LOAD_dict = {self.DOWNLOAD: self.download,
self.UPLOAD: self.upload}
self.save_path = _save_path
self.pathdict = {}
self.infodict = {}
self.setObjectName("FileDisplayWindow")
self.resize(666, 421)
font = QtGui.QFont()
font.setFamily("Consolas")
self.setFont(font)
self.setWindowTitle(QtCore.QCoreApplication.translate("Dialog", "Files"))
self.itemClicked.connect(self.fileClicked)
self.menu = QtWidgets.QMenu(self)
open_file = QtWidgets.QAction(QtGui.QIcon("images/file.png"), '打开文件', self)
open_file.triggered.connect(self.startfile)
self.menu.addAction(open_file)
open_path = QtWidgets.QAction(QtGui.QIcon("images/folder.png"), '打开文件夹', self)
open_path.triggered.connect(self.startpath)
self.menu.addAction(open_path)
QtCore.QMetaObject.connectSlotsByName(self)
def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
super().mousePressEvent(event)
if event.button() == QtCore.Qt.RightButton and self.itemAt(event.pos()):
item = self.itemAt(event.pos())
index: int = item.index_name
self.fpath = self.pathdict[index]
self.path = os.path.dirname(self.fpath)
self.menu.exec(event.globalPos())
@QtCore.pyqtSlot(str, int, int, tuple)
def new_file(self, name, total, size, info):
self.activateWindow()
index = len(self.infodict)
_type, local_file = info
_c = _cSpeed(total)
layout = FileListWidget.ListWidgetLayout(name, _c)
self.pathdict[index] = local_file
self.infodict[index] = (_c, name, os.path.dirname(local_file))
item = FileListWidget.ListItem(self, self.LOAD_dict.get(_type, self.UPLOAD), index, layout)
self.show()
@QtCore.pyqtSlot(int)
def update_file(self, index: int):
_c: _cSpeed = self.infodict[index][0]
_c.update_value(1)
def fileClicked(self, item: ListItem):
index = item.index_name
self.dialog = ProgressDialog(*self.infodict[index])
self.dialog_index = index
def startfile(self, *args):
if isinstance(self.fpath, str) and os.path.isfile(self.fpath):
os.startfile(self.fpath)
def startpath(self, *args):
if isinstance(self.path, str) and os.path.isdir(self.path):
os.startfile(self.path)
def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
super(FileListWidget, self).mouseMoveEvent(event)
self.x, self.y = event.x(), event.y()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
a = FileListWidget(os.path.join(os.path.dirname(os.path.realpath(__file__)), "database", "resource"))
a.new_file("asdf", 1010, 11111, (0, "C:/users/zhnwe/desktop/1.rte"))
a.executeDelayedItemsLayout()
for x in range(100):
a.update_file(0)
app.exec_()
依赖项目文件
ImageLoader.py
图片文件位于ServerProject 项目内的 user > images > filetype 下 地址位于 https://gitcode.net/m0_60394896/python
import os
path = "images/filetype"
unknown = os.path.join(path, "unknown.png").replace("\\", "/")
filedict = {}
def join(filename):
return os.path.join(path, filename).replace("\\", "/")
def get_suffix_img(suf):
return filedict.get(suf, unknown)
def get_suf(filename):
_, suf = os.path.splitext(filename)
return suf.lstrip(".").lower()
def get(filename):
return get_suffix_img(get_suf(filename))
for file in os.listdir(path):
filepath = join(file)
filetype, _ = os.path.splitext(file)
filedict[filetype.lower()] = filepath
functions.py
base = 1024
def _conv(value: (float, int)) -> str:
value = float(value)
if value.is_integer():
return str(int(value))
else:
return str(round(value, 1))
def convert(byte, fine=False):
"""
位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位。
字节 byte:8个二进制位为一个字节(B),最常用的单位。
其中1024=2^10 ( 2 的10次方),
1KB (Kilo byte 千字节)=1024B,
1MB (Mega byte 兆字节 简称“兆”)=1024KB,
1GB (Giga byte 吉字节 又称“千兆”)=1024MB,
1TB (Trillion byte 万亿字节 太字节)=1024GB,
1PB(Peta byte 千万亿字节 拍字节)=1024TB,
1EB(Exa byte 百亿亿字节 艾字节)=1024PB"""
if not isinstance(byte, (int, float)):
byte = len(byte)
DEI = f"{byte} bytes"
units = ["b",
"Kb",
"Mb",
"Gb",
"Tb",
"Pb",
"Eb"]
index = 0
while True:
if byte < 1024 or index + 1 >= len(units):
break
byte /= base
index += 1
if fine:
return f"{_conv(byte)}{units[index]}({DEI})"
else:
return f"{_conv(byte)}{units[index]}"
def to_logging(logger):
def log(command):
def _exec_func(*args, **kwargs):
try:
_result = command(*args, **kwargs)
if _result is None:
return True
return _result
except:
logger.exception(str())
return _exec_func
return log
|