python_PyQt5运行股票研究python方法工具V1.2_增加折线图控件

news2024/11/26 10:43:20

承接【python_PyQt5运行股票研究python方法工具V1.1_增加表格展示控件】

地址:python_PyQt5运行股票研究python方法工具V1.1_增加表格展示控件_程序猿与金融与科技的博客-CSDN博客

目录

 结果展示:

 代码:

示例py文件代码(低位股票分行业K线显示)

 参数json文件

 蜡烛控件

 K线图控件

多个K线图控件

批量截图下载线程

ExcuteShowWidget 中 process_excute_event 方法修改


 结果展示:

1 选择py文件所在目录

2 、3 选择要执行的py文件,点击“执行”

 4 执行结果再下拉列表中罗列

5 “截图下载”按钮,当前选项展示结果生成图形滚动下载

6 “批量截图”,将执行结果下拉列表中的所有结果都生成图形保存在指定目录下

 

 代码:

示例py文件代码(低位股票分行业K线显示)

def excute_code(json_obj:dict):
    '''
    批量K线对齐查看
    :param json_obj:
    :return:
    '''
    import pandas as pd
    import os

    code_list = json_obj['code_list']
    code_name_json = json_obj['code_name_json']
    daily_dir = json_obj['daily_dir']
    start_date = json_obj['start_date']
    end_date = json_obj['end_date']
    # second_level {行业名:[股票代码]}
    second_level = json_obj['second_level']

    res_target_name_map = {}

    all_k_json = {}
    for code in code_list:
        daily_file_path = daily_dir + os.path.sep + code + '.csv'
        one_df = pd.read_csv(daily_file_path,encoding='utf-8')
        one_df['o_date'] = pd.to_datetime(one_df['tradeDate'])
        one_df = one_df.loc[(one_df['o_date'] >= start_date) & (one_df['o_date'] <= end_date)].copy()
        one_df = one_df.loc[one_df['openPrice'] > 0].copy()
        one_df['o'] = one_df['openPrice'] * one_df['accumAdjFactor']
        one_df['c'] = one_df['closePrice'] * one_df['accumAdjFactor']
        one_df['h'] = one_df['highestPrice'] * one_df['accumAdjFactor']
        one_df['l'] = one_df['lowestPrice'] * one_df['accumAdjFactor']
        one_df['chgPct'] = one_df['chgPct']*100

        whole_data = one_df.loc[:,['c','o','h','l']].values.tolist()
        whole_header = ['收','开','高','低']
        whole_xTick = one_df['tradeDate'].values.tolist()
        y_min = one_df['l'].min()
        y_max = one_df['h'].max()

        one_map = {
            'graph_type':'k',
            'title_str':code_name_json[code],
            'whole_data':whole_data,
            'whole_header':whole_header,
            'whole_xTick':whole_xTick,
            'y_min':y_min,
            'y_max':y_max
        }

        all_k_json[code] = one_map
        pass

    for key,val in second_level.items():
        one_list = []
        for item in val:
            one_list.append(all_k_json[item])
        res_target_name_map[key] = one_list
        pass

    target_style = 'graph'
    target_data = res_target_name_map

    final_map = {
        'target_style':target_style,
        'target_data':target_data
    }
    return final_map

 参数json文件

{
	"code_list":["000025","000031","000058","000061","000068","000096","000410","000428","000503","000509","000514","000523","000536","000548","000557","000558","000565","000566","000599","000605","000632","000638","000652","000655","000701","000709","000727","000755","000758","000767","000797","000825","000850","000856","000878","000897","000898","000901","000912","000927","000952","000958","000960","000972","001896","002022","002037","002047","002061","002097","002106","002114","002160","002168","002183","002217","002278","002285","002305","002339","002343","002344","002354","002366","002400","002427","002431","002479","002480","002500","002522","002542","002573","002642","002659","002672","002673","002676","002682","002712","002722","002783","002807","600022","600037","600058","600076","600100","600108","600115","600119","600149","600150","600156","600169","600198","600202","600239","600249","600287","600292","600299","600300","600307","600320","600322","600343","600358","600376","600397","600403","600423","600433","600448","600526","600550","600601","600604","600617","600623","600626","600629","600630","600637","600648","600649","600650","600651","600653","600675","600676","600679","600684","600686","600692","600705","600708","600712","600716","600726","600743","600748","600758","600783","600798","600800","600805","600815","600825","600844","600855","600864","600871","600874","600880","600881","600889","600939","600959","600960","600981","600986","601016","601106","601168","601198","601368","601588","601600","601718","601727","601766","601857","601866","601918","601989","601991","603021","603169","603817","603999"],
	"code_name_json":{"000025":"特力A",
"000031":"大悦城",
"000058":"深赛格",
"000061":"农产品",
"000068":"华控赛格",
"000096":"广聚能源",
"000410":"沈阳机床",
"000428":"华天酒店",
"000503":"国新健康",
"000509":"华塑控股",
"000514":"渝开发",
"000523":"广州浪奇",
"000536":"华映科技",
"000548":"湖南投资",
"000557":"西部创业",
"000558":"莱茵体育",
"000565":"渝三峡A",
"000566":"海南海药",
"000599":"青岛双星",
"000605":"渤海股份",
"000632":"三木集团",
"000638":"万方发展",
"000652":"泰达股份",
"000655":"金岭矿业",
"000701":"厦门信达",
"000709":"河钢股份",
"000727":"冠捷科技",
"000755":"山西路桥",
"000758":"中色股份",
"000767":"晋控电力",
"000797":"中国武夷",
"000825":"太钢不锈",
"000850":"华茂股份",
"000856":"冀东装备",
"000878":"云南铜业",
"000897":"津滨发展",
"000898":"鞍钢股份",
"000901":"航天科技",
"000912":"泸天化",
"000927":"中国铁物",
"000952":"广济药业",
"000958":"电投产融",
"000960":"锡业股份",
"000972":"中基健康",
"001896":"豫能控股",
"002022":"科华生物",
"002037":"保利联合",
"002047":"宝鹰股份",
"002061":"浙江交科",
"002097":"山河智能",
"002106":"莱宝高科",
"002114":"罗平锌电",
"002160":"常铝股份",
"002168":"惠程科技",
"002183":"怡亚通",
"002217":"合力泰",
"002278":"神开股份",
"002285":"世联行",
"002305":"南国置业",
"002339":"积成电子",
"002343":"慈文传媒",
"002344":"海宁皮城",
"002354":"天娱数科",
"002366":"融发核电",
"002400":"省广集团",
"002427":"尤夫股份",
"002431":"棕榈股份",
"002479":"富春环保",
"002480":"新筑股份",
"002500":"山西证券",
"002522":"浙江众成",
"002542":"中化岩土",
"002573":"清新环境",
"002642":"荣联科技",
"002659":"凯文教育",
"002672":"东江环保",
"002673":"西部证券",
"002676":"顺威股份",
"002682":"龙洲股份",
"002712":"思美传媒",
"002722":"物产金轮",
"002783":"凯龙股份",
"002807":"江阴银行",
"600022":"山东钢铁",
"600037":"歌华有线",
"600058":"五矿发展",
"600076":"康欣新材",
"600100":"同方股份",
"600108":"亚盛集团",
"600115":"中国东航",
"600119":"长江投资",
"600149":"廊坊发展",
"600150":"中国船舶",
"600156":"华升股份",
"600169":"太原重工",
"600198":"大唐电信",
"600202":"哈空调",
"600239":"云南城投",
"600249":"两面针",
"600287":"江苏舜天",
"600292":"远达环保",
"600299":"安迪苏",
"600300":"维维股份",
"600307":"酒钢宏兴",
"600320":"振华重工",
"600322":"天房发展",
"600343":"航天动力",
"600358":"国旅联合",
"600376":"首开股份",
"600397":"安源煤业",
"600403":"大有能源",
"600423":"柳化股份",
"600433":"冠豪高新",
"600448":"华纺股份",
"600526":"菲达环保",
"600550":"保变电气",
"600601":"方正科技",
"600604":"市北高新",
"600617":"国新能源",
"600623":"华谊集团",
"600626":"申达股份",
"600629":"华建集团",
"600630":"龙头股份",
"600637":"东方明珠",
"600648":"外高桥",
"600649":"城投控股",
"600650":"锦江在线",
"600651":"飞乐音响",
"600653":"申华控股",
"600675":"中华企业",
"600676":"交运股份",
"600679":"上海凤凰",
"600684":"珠江股份",
"600686":"金龙汽车",
"600692":"亚通股份",
"600705":"中航产融",
"600708":"光明地产",
"600712":"南宁百货",
"600716":"凤凰股份",
"600726":"华电能源",
"600743":"华远地产",
"600748":"上实发展",
"600758":"辽宁能源",
"600783":"鲁信创投",
"600798":"宁波海运",
"600800":"渤海化学",
"600805":"悦达投资",
"600815":"厦工股份",
"600825":"新华传媒",
"600844":"丹化科技",
"600855":"航天长峰",
"600864":"哈投股份",
"600871":"石化油服",
"600874":"创业环保",
"600880":"博瑞传播",
"600881":"亚泰集团",
"600889":"南京化纤",
"600939":"重庆建工",
"600959":"江苏有线",
"600960":"渤海汽车",
"600981":"汇鸿集团",
"600986":"浙文互联",
"601016":"节能风电",
"601106":"中国一重",
"601168":"西部矿业",
"601198":"东兴证券",
"601368":"绿城水务",
"601588":"北辰实业",
"601600":"中国铝业",
"601718":"际华集团",
"601727":"上海电气",
"601766":"中国中车",
"601857":"中国石油",
"601866":"中远海发",
"601918":"新集能源",
"601989":"中国重工",
"601991":"大唐发电",
"603021":"山东华鹏",
"603169":"兰石重装",
"603817":"海峡环保",
"603999":"读者传媒"},
	"daily_dir":"E:/daily/",
	"start_date":"2023-07-01",
	"end_date":"2023-08-11",
	"second_level":{"\u4ea4\u901a\u8fd0\u8f93": ["000548", "000557", "000755", "002183", "002682", "600115", "600119", "600650", "600798", "601866"], "\u4f20\u5a92": ["002343", "002354", "002400", "002712", "600037", "600358", "600637", "600825", "600959", "600986", "603999"], "\u516c\u7528\u4e8b\u4e1a": ["000767", "001896", "002479", "002480", "600149", "600617", "600726", "601016", "601991"], "\u519c\u6797\u7267\u6e14": ["000972", "600108"], "\u533b\u836f\u751f\u7269": ["000566", "000952", "002022"], "\u5546\u8d38\u96f6\u552e": ["000058", "000061", "002344", "600058", "600287", "600712", "600981"], "\u56fd\u9632\u519b\u5de5": ["600150", "601989"], "\u57fa\u7840\u5316\u5de5": ["000565", "000912", "002037", "002427", "002522", "002783", "600299", "600423", "600623", "600844", "600889"], "\u5bb6\u7528\u7535\u5668": ["002676"], "\u5efa\u7b51\u88c5\u9970": ["002047", "002061", "002431", "002542", "600629", "600939"], "\u623f\u5730\u4ea7": ["000031", "000514", "000558", "000797", "000897", "002285", "002305", "600239", "600322", "600376", "600604", "600648", "600649", "600675", "600684", "600692", "600708", "600716", "600743", "600748", "601588"], "\u6709\u8272\u91d1\u5c5e": ["000758", "000878", "000960", "002114", "002160", "601168", "601600"], "\u673a\u68b0\u8bbe\u5907": ["000410", "000856", "000927", "002097", "002278", "600169", "600202", "600320", "600343", "600783", "600815", "601106", "601766", "603169"], "\u6c7d\u8f66": ["000599", "000901", "600626", "600653", "600679", "600686", "600960"], "\u7164\u70ad": ["600397", "600403", "600758", "601918"], "\u73af\u4fdd": ["000068", "000605", "002573", "002672", "600292", "600526", "600874", "601368", "603817"], "\u7535\u529b\u8bbe\u5907": ["002168", "002339", "002366", "600550", "601727"], "\u7535\u5b50": ["000509", "000536", "000701", "000727", "002106", "002217", "600601", "600651"], "\u77f3\u6cb9\u77f3\u5316": ["000096", "600800", "600871", "601857"], "\u793e\u4f1a\u670d\u52a1": ["000428", "002659", "600880"], "\u7eba\u7ec7\u670d\u9970": ["000850", "002722", "600156", "600448", "600630", "601718"], "\u7efc\u5408": ["000025", "000632", "000652", "600676", "600805", "600881"], "\u7f8e\u5bb9\u62a4\u7406": ["000523", "600249"], "\u8ba1\u7b97\u673a": ["000503", "000638", "002642", "600100", "600855"], "\u8f7b\u5de5\u5236\u9020": ["600076", "600433", "603021"], "\u901a\u4fe1": ["600198"], "\u94a2\u94c1": ["000655", "000709", "000825", "000898", "600022", "600307"], "\u94f6\u884c": ["002807"], "\u975e\u94f6\u91d1\u878d": ["000958", "002500", "002673", "600705", "600864", "601198"], "\u98df\u54c1\u996e\u6599": ["600300"]}
}

 蜡烛控件

class CandlestickItem(pg.GraphicsObject):
    def __init__(self, data):
        pg.GraphicsObject.__init__(self)
        self.data = data  ## data must have fields: time, open, close, min, max
        self.generatePicture()

    def generatePicture(self):
        ## pre-computing a QPicture object allows paint() to run much more quickly,
        ## rather than re-drawing the shapes every time.
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('d'))
        w = (self.data[1][0] - self.data[0][0]) / 3.
        for (t, open, close, min, max) in self.data:
            p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
            if open < close:
                p.setBrush(pg.mkBrush('r'))
            else:
                p.setBrush(pg.mkBrush('g'))
            p.drawRect(QtCore.QRectF(t-w, open, w * 2, close - open))
        p.end()

    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        ## boundingRect _must_ indicate the entire area that will be drawn on
        ## or else we will get artifacts and possibly crashing.
        ## (in this case, QPicture does all the work of computing the bouning rect for us)
        return QtCore.QRectF(self.picture.boundingRect())

 K线图控件

class GraphNodeTwoWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.whole_data = None
        self.whole_header = None
        self.whole_xTick = None
        self.y_min = None
        self.y_max = None
        pass
    def init_ui(self):
        self.setMinimumHeight(600)

        self.title_label = QtWidgets.QLabel()
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setStyleSheet('QLabel{font-size:26px;font-weight:bold;}')

        self.duration_label = QtWidgets.QLabel('左边界~右边界')

        layout_top = QtWidgets.QHBoxLayout()
        layout_top.addWidget(self.duration_label)
        layout_top.addStretch(1)

        self.pw = pg.PlotWidget()
        self.pw.setMouseEnabled(x=True, y=False)
        self.pw.setAutoVisible(x=False, y=True)
        # 不显示坐标轴
        self.pw.getPlotItem().hideAxis('bottom')
        self.pw.getPlotItem().hideAxis('left')

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.title_label)
        layout.addLayout(layout_top)
        layout.addWidget(self.pw)
        self.setLayout(layout)
        pass
    def set_data(self,data:Dict):
        graph_type = data['graph_type']
        title_str = data['title_str']
        self.whole_data = data['whole_data']
        self.whole_header = data['whole_header']
        self.whole_xTick = data['whole_xTick']
        self.y_min = data['y_min']
        self.y_max = data['y_max']
        if graph_type == 'k':
            self.set_k_data()
            pass
        self.title_label.setText(title_str)
        self.duration_label.setText(f"{self.whole_xTick[0]}~{self.whole_xTick[-1]}")
        pass
    def set_k_data(self):
        '''
        whole_data: [[c,o,h,l],[c,o,h,l],...]
        whole_header: [收,开,高,低]
        whole_xTick: 横坐标字符型
        :return:
        '''
        candle_data = []
        for i,row in enumerate(self.whole_data):
            candle_data.append((i,row[1],row[0],row[-1],row[-2]))
        self.pw.clear()
        self.vb = self.pw.getViewBox()
        self.vb.setLimits(yMin=self.y_min,yMax=self.y_max)
        candle_fixed_target = CandlestickItem(candle_data)
        self.pw.addItem(candle_fixed_target)

        self.pw.enableAutoRange()
        self.pw.setAutoVisible()
        pass
    pass

多个K线图控件

class GraphNodeWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.batch_download_qthread = None

        self.init_data()
        self.init_ui()
        pass
    def init_data(self):
        self.whole_data: Dict = None
        self.target_name_list: List = None
        self.current_target_name: str = None
        self.please_select_str: str = '-- 请选择 --'
        pass
    def init_ui(self):
        pre_btn = QtWidgets.QPushButton('上一个')
        pre_btn.clicked.connect(self.pre_btn_clicked)
        self.target_combox = QtWidgets.QComboBox()
        self.target_combox.currentTextChanged.connect(self.target_combox_currentTextChanged)
        next_btn = QtWidgets.QPushButton('下一个')
        next_btn.clicked.connect(self.next_btn_clicked)

        layout_one = QtWidgets.QHBoxLayout()
        layout_one.addStretch(1)
        layout_one.addWidget(pre_btn)
        layout_one.addWidget(self.target_combox)
        layout_one.addWidget(next_btn)
        layout_one.addStretch(1)

        self.title_label = QtWidgets.QLabel()
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setStyleSheet('QLabel{font-size:32px;font-weight:bold;}')

        onebyone_pic_shot_btn = QtWidgets.QPushButton('批量截图')
        onebyone_pic_shot_btn.clicked.connect(self.onebyone_pic_shot_btn_clicked)
        pic_shot_btn = QtWidgets.QPushButton('截图下载')
        pic_shot_btn.clicked.connect(self.pic_shot_btn_clicked)

        layout_two = QtWidgets.QHBoxLayout()
        layout_two.addStretch(1)
        layout_two.addWidget(pic_shot_btn)
        layout_two.addWidget(onebyone_pic_shot_btn)

        self.pw_layout = QtWidgets.QVBoxLayout()
        self.scroll_area = QtWidgets.QScrollArea()
        self.scroll_area.setWidgetResizable(True)

        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(layout_one)
        layout.addWidget(self.title_label)
        layout.addLayout(layout_two)
        layout.addWidget(self.scroll_area)
        self.setLayout(layout)
        pass
    def fill_scroll_area(self,widget_list:List):
        while self.pw_layout.count():
            item = self.pw_layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            pass
        sc_child_widget = self.scroll_area.takeWidget()
        if sc_child_widget is not None:
            sc_child_widget.deleteLater()
        for item in widget_list:
            self.pw_layout.addWidget(item)
        one_sc_child_widget = QtWidgets.QWidget()
        one_sc_child_widget.setLayout(self.pw_layout)
        self.scroll_area.setWidget(one_sc_child_widget)
        pass
    def pic_shot_btn_clicked(self):
        timestamp_str = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        name_str = self.current_target_name.replace(',','_')
        path,_ = QtWidgets.QFileDialog.getSaveFileName(
            self,
            '选择当前图片存储路径',
            f"pic_{name_str}_{timestamp_str}",
            'JPG(*.jpg)'
        )
        if not path:
            return

        widget = self.scroll_area.widget()
        pix = widget.grab()
        pix.save(path)
        pass
    def set_data(self,data:Dict):
        self.target_combox.clear()

        self.whole_data = data['data']
        self.target_name_list = list(self.whole_data.keys())
        self.current_target_name = self.target_name_list[0]

        self.target_combox.addItem(self.please_select_str)
        self.target_combox.addItems(self.target_name_list)

        self.fill_graph_content()
        pass
    def pre_btn_clicked(self):
        cur_i = self.target_name_list.index(self.current_target_name)
        if cur_i<=0:
            cur_i = len(self.target_name_list)-1
        else:
            cur_i = cur_i -1
        self.current_target_name = self.target_name_list[cur_i]
        self.fill_graph_content()
        pass
    def next_btn_clicked(self):
        cur_i = self.target_name_list.index(self.current_target_name)
        if cur_i >= len(self.target_name_list) - 1:
            cur_i = 0
        else:
            cur_i = cur_i + 1
        self.current_target_name = self.target_name_list[cur_i]
        self.fill_graph_content()
        pass
    def target_combox_currentTextChanged(self,txt:str):
        cur_txt = self.target_combox.currentText()
        if not cur_txt or cur_txt == self.please_select_str:
            return
        self.current_target_name = cur_txt
        self.fill_graph_content()
        pass
    def fill_graph_content(self):
        # {name:[[],[],...]}
        current_target_data = self.whole_data[self.current_target_name]
        widget_list = []
        for item in current_target_data:
            one_w = GraphNodeTwoWidget()
            one_w.set_data(item)
            widget_list.append(one_w)
            pass
        self.fill_scroll_area(widget_list)
        self.title_label.setText(self.current_target_name)
        pass
    def onebyone_pic_shot_btn_clicked(self):
        reply = QtWidgets.QMessageBox.question(
            self,
            '批量截图',
            '如果下拉列表中选项很多,将会耗费较长时间,并且这个区间工具可能无法操作',
            QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
            QtWidgets.QMessageBox.No,
        )
        if reply == QtWidgets.QMessageBox.Yes:
            path = QtWidgets.QFileDialog.getExistingDirectory(
                self,
                '打开截图要保存的文件夹',
                '.'
            )
            if not path:
                return
            self.onebyone_dowload_pic(path)
            pass
        pass
    def onebyone_dowload_pic(self,dir_path:str):
        self.batch_download_qthread = OneByOneDownloadThread()
        self.batch_download_qthread.finished.connect(self.batch_download_qthread_finished)
        self.batch_download_qthread.set_data(self.whole_data,dir_path)
        pass
    def batch_download_qthread_finished(self):
        QtWidgets.QMessageBox.information(
            self,
            '提示',
            '批量下载执行完毕',
            QtWidgets.QMessageBox.Yes
        )
        self.batch_download_qthread = None
        pass
    pass

批量截图下载线程

class OneByOneDownloadThread(QtCore.QThread):
    def __init__(self):
        super().__init__()
        self.data = None
        self.dir_path = None
        pass
    def set_data(self,data:Dict,dir_path:str):
        self.data = data
        self.dir_path = dir_path + os.path.sep
        self.start()
        pass
    def run(self):
        timestamp_str = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        for key,val in self.data.items():
            key_str = key.replace(',','_')
            file_name = f'{self.dir_path}{key_str}_{timestamp_str}.jpg'
            one_widget = QtWidgets.QWidget()
            one_layout = QtWidgets.QVBoxLayout()
            for item in val:
                one_w = GraphNodeTwoWidget()
                one_w.set_data(item)
                one_layout.addWidget(one_w)
                pass
            one_widget.setLayout(one_layout)
            pix = one_widget.grab()
            pix.save(file_name)
            pass
        pass

ExcuteShowWidget 中 process_excute_event 方法修改

    def process_excute_event(self,data:Dict):
        mark_str = data['mark_str']
        status = data['status']
        if status == 'success':
            self.excute_info_label.setText(f'{mark_str} 执行成功')

            ret = data['ret']
            target_style = ret['target_style']
            if target_style == 'table':
                # 表格类型结果
                pre_map = {
                    'header':ret['target_header'],
                    'data':ret['target_data']
                }
                node_widget = TableNodeWidget()
                node_widget.set_data(pre_map)
                self.fill_scroll_area([node_widget])
                pass
            elif target_style == 'graph':
                # 图类型
                pre_map = {
                    'data':ret['target_data']
                }
                node_widget = GraphNodeWidget()
                node_widget.set_data(pre_map)
                self.fill_scroll_area([node_widget])
                pass

            self.thread_caculate = None
            self.progress_finished()
            pass
        else:
            self.excute_info_label.setText(f'{mark_str} 失败!失败!')
            now_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            log_str = f'{now_str}::{mark_str}::{data["msg"]}'
            self.log_list.append(log_str)

            self.thread_caculate = None
            self.progress_finished()
            pass
        pass

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/877909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【go语言学习笔记】05 Go 语言实战

文章目录 一、 RESTful API 服务1. RESTful API 定义1.1 HTTP Method1.2 RESTful API 规范 2. RESTful API 风格示例3. RESTful JSON API4. Gin 框架4.1 导入 Gin 框架4.2 使用 Gin 框架4.2.1 获取特定的用户&#xff08;GET&#xff09;4.2.2 新增一个用户&#xff08;POST&am…

一位年薪50W的测试被开除,回怼的一番话,令人沉思

一位年薪35W测试工程师被开除回怼道&#xff1a;“反正我有技术&#xff0c;在哪不一样” 一技傍身&#xff0c;万事不愁&#xff0c;当我们掌握了一技之长后&#xff0c;在职场上说话就硬气了许多&#xff0c;不用担心被炒&#xff0c;反过来还可以炒了老板&#xff0c;这一点…

前后端分离------后端创建笔记(05)用户列表查询接口(上)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

推荐5款能帮你解决各种问题的神器

​ 今天我要向大家推荐5款超级好用的效率软件&#xff0c;无论是在学习还是办公中都能够极大地提高效率。这些软件可以帮助你解决许多问题&#xff0c;而且每个都是真正的神器。 网速和硬件监控——TrafficMonitor ​ TrafficMonitor 是一款可以在任务栏或桌面悬浮窗显示系统…

配置service管理nginx

一.以源码形式安装的nginx&#xff0c;没有nginx.service 二.切换到service配置目录 三.编辑nginx.service文件 四.启动测试 1.我的开始报了这个问题&#xff0c;说没有这个/var/cache/nginx/client_temp目录&#xff0c;直接创建一个就好了 2.开启/关闭 一.以源码形式安装…

参加NPCon2023 AI模型技术与应用峰会(北京站):作为北京社区主理人的参会感受

参加NPCon2023 AI模型技术与应用峰会&#xff1a;作为北京社区主理人的参会感受 &#x1f3c9;&#x1f3c9;前言&#x1f3c9;&#x1f3c9;活动周边琳琅满目&#x1f3c9;&#x1f3c9;主题演讲&#x1f3c9;&#x1f3c9;亮点&#x1f3c9;&#x1f3c9;总结与展望 博主 默语…

项目管理的艺术:掌握成本效益分析

引言 在项目管理中&#xff0c;我们经常面临着如何有效地使用有限的资源来实现项目目标的挑战。为了解决这个问题&#xff0c;我们需要使用一种强大的工具——成本效益分析。通过成本效益分析&#xff0c;我们可以评估和比较不同的项目选项&#xff0c;选择最具成本效益的项目…

备战2024秋招面试题-最左匹配原则、索引失效情况、算法(最长回文子串)

前言&#xff1a; \textcolor{Green}{前言&#xff1a;} 前言&#xff1a; &#x1f49e;快秋招了&#xff0c;那么这个专栏就专门来记录一下&#xff0c;同时呢整理一下常见面试题 &#x1f49e;部分题目来自自己的面试题&#xff0c;部分题目来自网络整理 给我冲 学习目标&am…

Python爬虫——scrapy_基本使用

安装scrapy pip install scrapy创建scrapy项目&#xff0c;需要在终端里创建 注意&#xff1a;项目的名字开头不能是数字&#xff0c;也不能包含中文 scrapy startproject 项目名称 示例&#xff1a; scrapy startproject scra_baidu_36创建好后的文件 3. 创建爬虫文件&…

【构造】CF1761 E

Problem - 1761E - Codeforces 题意&#xff1a; 思路&#xff1a; Code&#xff1a; #include <bits/stdc.h>using i64 long long;void solve() {int n;std::cin >> n;std::vector g(n, std::vector<int>(n));std::vector<int> deg(n);for (int i …

电脑xinput1_3.dll丢失的解决方法?哪个解决方法更简单

最近在打开软件或者游戏的时候&#xff0c;电脑提示xinput1_3.dll文件丢失的错误。这个问题导致我无法运行某些游戏和应用程序。通过一番尝试和研究&#xff0c;我找到了一些修复xinput1_3.dll文件丢失的方法&#xff0c;并在此分享给大家。 首先&#xff0c;我了解到xinput1_3…

让音频翻译软件成为你的翻译利器吧

音频翻译功能是现代技术的一大进步&#xff0c;它通过语音识别技术和机器翻译技术&#xff0c;可以将音频文件自动翻译成其他语言的文字&#xff0c;让人们跨越语言障碍进行交流。现在市面上有很多种音频文件翻译软件&#xff0c;每个软件都有其独特的功能和特点。那么&#xf…

【状态模式】拯救if-else堆出来的屎山代码

前言 我想大家平时都在开发重都遇见过屎山代码&#xff0c;这些屎山代码一般都是由于复杂且庞大的if-else造成的&#xff0c;状态模式&#xff0c;是一种很好的优化屎山代码的设计模式&#xff0c;本文将采用两个业务场景的示例来讲解如何使用状态模式拯救屎山代码。 目录 前…

什么是管理的本质?

管理不是一门硬科学。与&#xff08;通常&#xff09;存在正确答案的化学或代数不同&#xff0c;管理是流动的&#xff0c;主观的&#xff0c;并且对于如何运用其原理存在不同的观点。但究竟什么是管理&#xff1f;大多数学者都有相同定义的变体&#xff0c;包括利用资源来实现…

Ubuntu系统搭建socks5代理 Danted SOCKS Proxy

本教程介绍如何在Ubuntu系统中搭建Dated Socks5 代理服务器 更新系统 apt update安装 danted软件 apt install dante-server修改该danted软件的配置文件 vi /etc/danted.conf修改后的内容为下&#xff1a; logoutput: syslog user.privileged: root user.unprivileged: no…

沁恒ch32V208处理器开发(五)复用与重映射

目录 概述实现方法GPIO 及其复用功能AFIO 的寄存器实现 重映射的功能限制 概述 在ch32V2xx系列处理器中&#xff0c;芯片引脚数从28到68不等&#xff0c;分为几个系列&#xff0c;不同型号之间外设资源有差异&#xff0c;所以&#xff0c;引脚复用和重映射功能 也不一样&#…

jmeter获取mysql数据

JDBC Connection Configuration Database URL: jdbc:mysql:// 数据库地址 /库名 JDBC Driver class&#xff1a;com.mysql.jdbc.Driver Username&#xff1a;账号 Password&#xff1a;密码 JDBC Request 字段含义 字段含义 Variable Name Bound to Pool 数据库连接池配置…

分类预测 | MATLAB实现GWO-BiGRU-Attention多输入分类预测

分类预测 | MATLAB实现GWO-BiGRU-Attention多输入分类预测 目录 分类预测 | MATLAB实现GWO-BiGRU-Attention多输入分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.GWO-BiGRU-Attention 数据分类预测程序 2.代码说明&#xff1a;基于灰狼优化算法&#xff08;GW…

这四种订货系统不能选(二):不能独立部署

订货系统在传统批发贸易企业数字化转型中扮演着重要的角色。然而&#xff0c;有一种类型的订货系统并不适合选择&#xff0c;那就是无法独立部署的系统。 无法独立部署的订货系统意味着数据必须存放在软件厂商的服务器上。当我们选择这样的系统时&#xff0c;需要确保系统具备强…

C++11并发与多线程笔记 (1)

C11并发与多线程笔记&#xff08;1&#xff09; 1、并发、进程、线程的基本概念和综述1.1 并发1.2 可执行程序1.3 进程1.4 线程1.5 学习心得 2、并发的实现方法2.1 多进程并发2.2 多线程并发 3、C11新标准线程库 1、并发、进程、线程的基本概念和综述 1.1 并发 指在一个时间段…