改动python源代码,实现每次调用list.append方法,自动输出一行debug信息

0.直接重写list类完全可以解决,但是我想了解一下python源码的底层。因此,自己编译源代码安装

1.下载源代码

在git中下载源代码,或者使用git clone。这里我是直接下载的。我下载到了 $HOME/python/source

2.先测试一下,使用源码编译
2.1 进入源代码根目录

cd $HOME/python/source/cpython3.12

2.2 配置安装选项(这里我指定了安装位置)

./configure --prefix=$HOME/python/source/have_compiled/test_cpython

2.3编译并安装

make -j$(noproc)

make install

2.4测试

cd $HOME/python/source/have_compiled/test_python/bin

./python3.12

会成功进入交互命令行,并且最开头会显示安装时间。从源码包安装才是最接近windows安装应用的形式。删除也非常方便

  1. 更改源代码,来重新编译
    3.1 在 Objects/listobject.c中,找到append的实现。如下
static PyObject *
list_append(PyListObject *self, PyObject *object)
/*[clinic end generated code: output=7c096003a29c0eae input=43a3fe48a7066e91]*/
{
    if (_PyList_AppendTakeRef(self, Py_NewRef(object)) < 0) {
        return NULL;
    }
    Py_RETURN_NONE;
}

3.2. 添加打印语句,注意不要在if语句中添加打印语句,否则只有添加返回错误,才会出现。

static PyObject *
list_append(PyListObject *self, PyObject *object)
/*[clinic end generated code: output=7c096003a29c0eae input=43a3fe48a7066e91]*/
{
    if (_PyList_AppendTakeRef(self, Py_NewRef(object)) < 0) {
        return NULL;
    }
    printf("Debug: add a element");
    Py_RETURN_NONE;
}
  1. 使用make clean来清除编译,之后重复2。由于使用了printf,而不是/
    PySys_WriteStderr(“Debug: add element %R\n”, object),运行的结果如下:
Type "help", "copyright", "credits" or "license" for more information.
mentDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a elementDebug: add a element>>> l = []
>>> l.append('a')
Debug: add a element>>>

也基本算是完成了目标

#!/bin/env python # 必须写在第一行 -- coding: utf-8 -- ################################################# Author: songwenhua Function:客户阻抗线连续性检查 Date: 2025-11-05 v1.00 songwenhua 用户需求号: 2482 任务ID:2100 /home/incam/Desktop/scripts/shendan/check_Y_zk_line LOAD_MODE__ import os import re import sys from py39COM import Gateway, InCAM from py39Tools import TableWidget from ICO import ICO from ICNET import ICNET from XMLParse import XMLParsePlus from messageBox import messageBox from EqHelper import EqHelper from PyQt5.QtWidgets import QWidget, QApplication, QComboBox from collections import defaultdict, deque from functools import partial import math from img import apprcc_rc from pprint import pprint import time class chk_Conti_zkline: def __init__(self): # self.setWindowFlags(Qt.WindowStaysOnTopHint) self.JOB = os.environ.get('JOB', None) self.STEP = os.environ.get('STEP', None) # self.chklist = os.environ.get('chklist', None) # --启动pycharm.sh时,里面有export INCAM_DEBUG=yes设置此环境变量 INCAM_DEBUG = os.getenv('INCAM_DEBUG', None) # 接口定义 if INCAM_DEBUG == 'yes': # 通过genesis gateway命令连结pid进行会话,不用在genesis环境下运行,直接用gateway的方式,可在pycharm环境下直接debug self.incam = Gateway() # 方法genesis_connect通过查询log-genesis文件获取的料号名 self.JOB = self.incam.job_name self.STEP = self.incam.step_name self.pid = self.incam.pid else: self.incam = InCAM() self.pid = os.getpid() self.ico = ICO(incam=self.incam) self.icNet = ICNET(incam=self.incam) self.jobName = self.ico.SimplifyJobName(jobName=self.JOB) self.dbSite = self.ico.GetDBSite(JOB=self.JOB) self.SITE = self.ico.GetSite(JOB=self.JOB) self.getinfomation_dict = defaultdict(defaultdict) self.ballPadIndexList = defaultdict(list) self.layerMatrix = self.ico.GetLayerMatrix() self.zkLineIndex = defaultdict(defaultdict) self.step_list = self.ico.GetStepList() layer_list = self.ico.GetLayerList() self.zk_siglay = {} self.zkLayerList = self.getZKLayer() # 获取阻抗线层别 self.run() def getZKLayer(self): """ 获取阻抗线层别 :return: 阻抗线层别 """ zkLayerList = list() layerList = self.layerMatrix['allLay'] # self.ico.GetLayerList() for lay in layerList: for t in ('s', 'ss', 'gsg', 'gssg'): # pattern_tmp = re.compile(r'^((?:un-)?(\d+|[tb])zk)-(\d+\.?\d*)-(%s)-?(\d+\.?\d*)?-?(\d+\.?\d*)?-?(\d+\.?\d*)?$' % t)#存在un开头的阻抗层 pattern_tmp = re.compile(r'^((\d+|[tb])zk)-(\d+\.?\d*)-(%s)-?(\d+\.?\d*)?-?(\d+\.?\d*)?-?(\d+\.?\d*)?$' % t) matchObj = re.match(pattern_tmp, lay) if matchObj: matchList = matchObj.groups() zkLayerList.append(lay) self.getinfomation_dict[lay]['layer'] = matchList[0] print(zkLayerList) if len(zkLayerList) > 0: SignalLayer_list = self.layerMatrix['sigAllLay'] for i in range(len(SignalLayer_list)): if i == 0: self.zk_siglay['tzk'] = SignalLayer_list[0] elif i == (len(SignalLayer_list) - 1): self.zk_siglay['bzk'] = SignalLayer_list[-1] else: self.zk_siglay[str(i + 1) + 'zk'] = SignalLayer_list[i] # self.zk_siglay['un-' + str(i + 1) + 'zk'] = SignalLayer_list[i]#还要加一个un-开头的对应线路层! print("zk_siglay : %s" % self.zk_siglay) for lay in self.getinfomation_dict.keys(): for key in self.zk_siglay: if self.getinfomation_dict[lay]['layer'] == key: self.getinfomation_dict[lay]['sigLayerNum'] = str(SignalLayer_list.index(self.zk_siglay[key]) + 1) self.getinfomation_dict[lay]['sigLayerName'] = str(self.zk_siglay[key]) break else: messageBox.showMessage(message='没有识别到阻抗线层别,请规范命名(eg:tzk-gssg-100)', bitmap='critical') exit() return zkLayerList def get_unique_endpoints_single_layer(self, step, backup_layer): """ 仅从单个 backup_layer 提取端点(仅本层内统计) """ self.ico.ClearLayer() self.ico.DispWork(backup_layer) features = self.ico.GetFeatureFullInfo(step, layer=backup_layer) if not features: return [] layer_endpoints = [] for feat in features: ftype = feat['type'] if ftype in ('line', 'arc'): xs, ys = feat['x0'], feat['y0'] xe, ye = feat['x1'], feat['y1'] layer_endpoints.append((round(xs, 6), round(ys, 6))) layer_endpoints.append((round(xe, 6), round(ye, 6))) point_count = defaultdict(int) for pt in layer_endpoints: point_count[pt] += 1 unique_ends = [pt for pt, cnt in point_count.items() if cnt == 1] unique_ends.sort(key=lambda p: (p[0], p[1])) print(f"{backup_layer}: 找到 {len(unique_ends)} 个唯一端点") return unique_ends def selectun_separate(self, backup_layer, zkLay, target_temp_layer): """ 在原始信号层上选出与 backup_layer 接触的所有非 line/arc 图形, 复制到指定的 target_temp_layer 并合并成 surface。 """ try: zk2SigLay = self.getinfomation_dict[zkLay]['sigLayerName'] except KeyError as e: return False self.ico.ClearAll() self.incam.COM("adv_filter_reset") self.incam.COM(f"display_layer, name={zk2SigLay}, display=yes") self.incam.COM(f"work_layer, name={zk2SigLay}") self.incam.COM("set_filter_type,filter_name=,lines=no,pads=yes,surfaces=yes,arcs=no,text=yes") self.incam.COM("set_filter_polarity,filter_name=,positive=yes,negative=yes") self.incam.COM(f"sel_ref_feat,layers={backup_layer},use=filter,mode=touch,pads_as=shape," "f_types=line;pad;surface;arc;text,polarity=positive;negative,include_syms=,exclude_syms=") self.incam.COM("get_select_count") count = int(self.incam.COMANS) if count == 0: return False # 复制到专属临时层 self.incam.COM(f"sel_copy_other, dest=layer_name, target_layer={target_temp_layer}, " "invert=no, dx=0, dy=0, size=0, x_anchor=0, y_anchor=0") # 切换到目标临时层并合并 self.ico.ClearAll() self.ico.DispWork(target_temp_layer) self.ico.TrySelContResize([2.54, 5, 10]) return True def selectBallPad(self, zkLay, x, y): """ 判断指定坐标点是否与背面ball pad导通 :param zkLay: 阻抗层名称 :param x: 检查点的x坐标 :param y: 检查点的y坐标 :return: bool 是否导通 """ # 阻抗层对应的线路层 zk2SigLay = self.getinfomation_dict[zkLay]['sigLayerName']#self.getinfomation_dict得到的是原始阻抗层,而不是_bak备份阻抗层 sigBot = self.layerMatrix['sigAllLay'][-1] #线路层最后一层,背面 # 设置工作环境 self.ico.ClearAll() self.ico.ResetFilter() self.incam.COM(f'affected_layer, name={sigBot}, mode=single, affected=yes') self.incam.COM(f'display_layer, name={zk2SigLay}, display=yes') self.incam.COM(f'work_layer, name={zk2SigLay}') # 执行选择 self.incam.COM("sel_clear_feat") #清除之前的选择 self.incam.COM("clear_highlight") self.incam.COM(f'sel_board_net_feat, operation=select, x={x}, y={y}, tol=1, use_ffilter=no') # 获取选中特征 featureFullInfo_sigBot = self.ico.GetFeatureFullInfo(step=self.STEP, layer=sigBot, mode='select') # 检查背面ball pad # 对于背面sig选到的物体,做个筛选,如果是pad且是.smd属性,说明选到了ball pad selectPadList = [info for info in featureFullInfo_sigBot if info['type'] == 'pad' and (info['attr'] == '.smd' or info['attr'] == '.smd,.bga' or info['attr'] == '.smd,.lga' or info['attr'] == '.smd,.smt_pad' or info['attr'] == '.smd,.test_pad')] # 20241209 新增ball pad属性是.smd.bga和.smd.lga return len(selectPadList) > 0 # 如果找到ball pad则返回True def cleanup_short_polylines(self, step, backup_layer, min_length=8.0): """ 删除总长度 < min_length 的整根 polyline(由多个 line 与arc 组成) 利用 feature['length'] 避免重复计算几何距离 """ features = self.ico.GetFeatures(step, backup_layer) # 提取所有 line 和 arc valid_features = [f for f in features if f['type'] in ('line', 'arc')] if not valid_features: return # #######构建拓扑图 端点->线段#### graph = defaultdict(list) # 坐标 -> 相邻坐标 coord_to_feats = defaultdict(list) # 坐标 -> (index, feature) for idx, feat in enumerate(valid_features): xs = round(feat['xs'], 3) ys = round(feat['ys'], 3) xe = round(feat['xe'], 3) ye = round(feat['ye'], 3) start = (xs, ys) end = (xe, ye) graph[start].append(end) graph[end].append(start) coord_to_feats[start].append((idx, feat)) coord_to_feats[end].append((idx, feat)) visited_coords = set() short_polyline_seeds = [] # 存储每根短 polyline 的一个起点用于删除 ##########BFS 遍历每个连通组件########### for coord in list(graph.keys()): if coord in visited_coords: continue queue = deque([coord]) current_visited_coords = set() current_feat_indices = set() while queue: curr = queue.popleft() if curr in current_visited_coords: continue current_visited_coords.add(curr) for neighbor in graph[curr]: # 查找连接 curr和neighbor 的 feature found = False for feat_idx, feat in coord_to_feats[curr]: if feat_idx in current_feat_indices: continue # 判断是否连接 curr 和 neighbor s = (round(feat['xs'],3), round(feat['ys'],3)) e = (round(feat['xe'],3), round(feat['ye'],3)) connected = (curr == s and neighbor == e) or (curr == e and neighbor == s) if connected: current_feat_indices.add(feat_idx) found = True break if not found: continue # 没有可用边 if neighbor not in current_visited_coords: queue.append(neighbor) # 标记这些点已被全局访问 visited_coords.update(current_visited_coords) if not current_feat_indices: continue ################计算当前 polyline 总长度########### total_length = sum(valid_features[i]['length'] for i in current_feat_indices) if total_length < min_length: # 找一个端点作为选择依据(度为1的点) endpoints = [pt for pt in current_visited_coords if len(graph[pt]) == 1] seed = endpoints[0] if endpoints else next(iter(current_visited_coords)) short_polyline_seeds.append(seed) ##########删除:选中所有短 polyline######### if short_polyline_seeds: self.incam.COM("sel_clear_feat") for x, y in short_polyline_seeds: # self.incam.COM(f"sel_polyline_feat,operation=select,x={x:.3f},y={y:.3f},tol=1") self.incam.COM(f"sel_polyline_feat,operation=select,x={x},y={y},tol=35.775,cyclic=yes,clear_prev=no") self.incam.COM("sel_delete") def delete_surfaces_covering_points(self, points, layer_new): """ 删除临时层中包含给定点的 surface :param points: list of (x, y) """ self.ico.ClearLayer() self.ico.DispWork(layer_new) self.incam.COM("sel_clear_feat") # 初始清空 tol = 0.05 # 匹配点的 filter 容差 selected_count = 0 for x, y in points: #用 FilterAreaXY 查找落在点附近的图形 # self.incam.COM("sel_clear_feat") # 临时清空 # x1, y1 = x - tol, y - tol # x2, y2 = x + tol, y + tol # count_in_area = self.ico.FilterAreaXY( # isInside='yes', # intersect='yes', # x1=x1, # y1=y1, # x2=x2, # y2=y2 # ) # self.incam.COM(f"sel_single_feat, operation=select, x={x}, y={y}, tol=0.1") self.incam.COM(f"sel_single_feat,operation=select,x={x},y={y},tol=35.775,cyclic=yes,clear_prev=no") self.incam.COM("get_select_count") current_count = int(self.incam.COMANS) # if current_count > selected_count: # selected_count = current_count # print(f"在点 ({x:.3f}, {y:.3f}) 处选择了图形") # 一次性删除所有选中的图形 if current_count > 0: self.incam.COM("sel_delete") # print(f"成功删除了 {current_count} 个覆盖末端点的 surface") # else: # print("未找到覆盖末端点的 surface") @staticmethod def extract_start_points(data): """ 支持输入为 str 或 list[str],统一处理并提取每个图形的 #OB 起点 """ if isinstance(data, list): # 如果是列表,用换行符拼接成字符串 content = "\n".join(data) elif isinstance(data, str): content = data else: raise TypeError("Input must be str or list of str") start_points = [] # 按 '#数字 #S' 分割出各个图形块 blocks = re.split(r'#(\d+)\s+#S', content)[1:] # 每两项:编号 + 内容 for i in range(0, len(blocks), 2): block_content = blocks[i+1] match = re.search(r'#OB\s+([-\d.]+)\s+([-\d.]+)', block_content) if match: x = float(match.group(1)) y = float(match.group(2)) start_points.append((x, y)) return start_points def get_coords(self, feature): """ 从任意图元中快速提取一个坐标点 (x, y) 特别处理 surface 的 orig 字段 """ # 处理 surface 的 orig if feature.get('type') == 'surface' and isinstance(feature.get('orig'), list): pattern = r'#O[BS]\s+([-\d.]+)\s+([-\d.]+)' for line in feature['orig']: match = re.search(pattern, line) if match: x = float(match.group(1)) y = float(match.group(2)) return round(x, 3), round(y, 3) # 返回第一个有效坐标即可 return None def run(self): """ 主执行函数:完成客户阻抗线连续性检查(分层处理版本) """ job = self.JOB step = 'edit' unthrough_lay = [] # 告警层记录 backup_layers = [] valid_touch_points = set() final_tmp_layer = 'tmp_total' # 最终合并用的临时层 temp_layers = [] # 存储每个 tmp_n 层名列表 self.ico.ClearAll() self.zkLineIndex = defaultdict(lambda: defaultdict(list)) ######## 创建备份层 ################## for idx, zklay in enumerate(self.zkLayerList): zkLay_bak = f'{zklay}_bak' layer_n = f'tmp_{idx + 1}' # 对应的独立临时层 temp_layers.append(layer_n) self.zkLineIndex[zklay]['zkLaybak'] = zkLay_bak self.zkLineIndex[zklay]['tempLayer'] = layer_n # 新增映射 # 删除旧备份层和临时层 self.ico.DelLayer(layer_list=[zkLay_bak, layer_n]) self.ico.DispWork(zklay) self.incam.COM(f'sel_copy_other,dest=layer_name,target_layer={zkLay_bak},invert=no,dx=0,dy=0,size=0,x_anchor=0,y_anchor=0') backup_layers.append(zkLay_bak) # 清空最终 tmp 层 self.ico.CreateOrEmptyLay(layer_list=[final_tmp_layer]) ######## 分层处理:复制 → 合并 → 删除末端覆盖 surface ######## for backup_layer in backup_layers: original_zklay = backup_layer.replace('_bak', '') temp_layer_n = self.zkLineIndex[original_zklay]['tempLayer'] print(f"处理 {backup_layer} => 使用临时层 {temp_layer_n}") # 步骤1: 复制非 line/arc 图形到 temp_layer_n has_copied = self.selectun_separate(backup_layer, original_zklay, temp_layer_n) if not has_copied: continue # 步骤2: 获取该 bak 层的唯一端点(仅本层内统计) unique_ends = self.get_unique_endpoints_single_layer(step, backup_layer) if not unique_ends: print(f"{backup_layer}: 无唯一端点,跳过 surface 删除") continue # 步骤3: 删除 temp_layer_n 中覆盖这些端点的 surface self.delete_surfaces_covering_points(unique_ends, temp_layer_n) ######## 合并所有 temp_layer_n 到 final_tmp_layer ######## self.ico.ClearAll() # 确保目标层存在且为空(可选) self.ico.CreateOrEmptyLay(layer_list=[final_tmp_layer]) for temp_layer in temp_layers: tmp_info = self.ico.GetFeatureFullInfo(step, temp_layer) if not tmp_info: continue # --- 开始复制该层 --- self.incam.COM(f"display_layer,name={temp_layer},display=yes") # 显示源层 self.incam.COM(f"work_layer,name={temp_layer}") # 设置为工作层 self.incam.COM("sel_all_feat") # 选择所有图形 # 将选中图形复制到 final_tmp_layer self.incam.COM(f"sel_copy_other,dest=layer_name,target_layer={final_tmp_layer}," "invert=no,dx=0,dy=0,size=0,x_anchor=-11.5,y_anchor=-11.5,subsystem=1-Up-Edit") print(f"已将 {temp_layer} 的内容复制到 {final_tmp_layer}") self.ico.ClearAll() # 清理选择状态 ######## 统一进行 ball pad 导通判断(基于合并后的 final_tmp_layer)######## for backup_layer in backup_layers: original_zklay = backup_layer.replace('_bak', '') self.ico.ClearAll() self.ico.DispWork(backup_layer) self.ico.DispLayer(final_tmp_layer) # 设置过滤器:只选 line self.incam.COM("adv_filter_reset") self.incam.COM("set_filter_type, lines=yes, pads=no, surfaces=no, arcs=no, text=no") self.incam.COM("set_filter_polarity, positive=yes, negative=yes") # 选择与 final_tmp_layer 接触的 line self.incam.COM(f"sel_ref_feat,layers={final_tmp_layer},use=filter,mode=touch,pads_as=shape," "f_types=line;pad;surface;arc;text,polarity=positive;negative,include_syms=,exclude_syms=") features = self.ico.GetFeatureFullInfo(step, layer=backup_layer, mode='select') if not features: continue connection_to_ballpad = False problem_coords = [] test_points = [(round(feat['x0'], 6), round(feat['y0'], 6)) for feat in features if feat['type'] in ('line', 'arc')] test_points = list(set(test_points)) for xs, ys in test_points: if self.selectBallPad(original_zklay, xs, ys): connection_to_ballpad = True problem_coords.append((xs, ys)) else: valid_touch_points.add((xs, ys)) if connection_to_ballpad: unthrough_lay.append({ 'layer': backup_layer, 'coords': problem_coords }) ######## 统一弹窗提示 ###### if unthrough_lay: # 提取所有出问题的原始层名(去掉 '_bak' 后缀) problem_layers = [item['layer'].replace('_bak', '') for item in unthrough_lay] layer_list_str = ', '.join(problem_layers) messageBox.showDialog( title='阻抗线与 Ball Pad 导通警告', text=f'{layer_list_str}层存在阻抗线不连续且与背面 Ball Pad 导通:\n\n' '1. 请确认是否为分流设计;\n' '2. 如为客户设计,请 EQ 客户确认是否允许;\n' '3. 如不允许,需内部评估并通知测量科邦控阻值。', bitmap='warning', buttons=['OK'], defaultButton='OK' ) sys.exit(0) ######## 清理 & 删除短 polyline 和孤立段 ######## for backup_layer in backup_layers: original_zklay = backup_layer.replace('_bak', '') self.ico.ClearAll() self.incam.COM("sel_clear_feat") current_step = 'edit' self.ico.DispWork(backup_layer) # 删除与 final_tmp_layer 接触的整根 polyline for x, y in valid_touch_points: self.incam.COM(f"sel_polyline_feat,operation=select,x={x},y={y},tol=35.775,cyclic=yes,clear_prev=no") self.incam.COM("sel_delete") # self.ico.ClearLayer() # 删除长度 < 8mm 的短 polyline self.cleanup_short_polylines(step=current_step, backup_layer=backup_layer, min_length=8.0) # 删除两端都不导通 ball pad 的孤立段 final_features = self.ico.GetFeaturesPro(job=job, step=current_step, layer=backup_layer) for feat in final_features: if feat['type'] not in ('line', 'arc'): continue xs, ys = round(feat['xs'], 3), round(feat['ys'], 3) xe, ye = round(feat['xe'], 3), round(feat['ye'], 3) start_ok = self.selectBallPad(original_zklay, xs, ys) end_ok = self.selectBallPad(original_zklay, xe, ye) if not (start_ok or end_ok): self.incam.COM(f"sel_polyline_feat,operation=select,x={xs},y={ys},tol=35.775,cyclic=yes,clear_prev=no") self.incam.COM("sel_delete") ######## 判断剩余内容并提示用户 ######## empty_layers = [] valid_layers = [] for backup_layer in backup_layers: remaining = self.ico.GetFeaturesPro(job=job, step='edit', layer=backup_layer) has_valid = any(f['type'] in ('line', 'arc') for f in remaining) if has_valid: valid_layers.append(backup_layer) else: empty_layers.append(backup_layer) msg_parts = [] if empty_layers: msg_parts.append(f'{", ".join(empty_layers)}存在阻抗线不连续,同组无可测阻抗线,与客户EQ此组阻抗通过测量科邦卡控阻值,如客户不同意,内部策划列难点评估测科邦') if valid_layers: msg_parts.append(f'{", ".join(valid_layers)}存在阻抗线不连续,同组存在可测阻抗线,EQ客户Y型阻抗线follow同组可测阻抗线进行调整') if msg_parts: messageBox.showDialog( title='提示', text='\n\n'.join(msg_parts), bitmap='warning', buttons=['OK'], defaultButton='OK' ) # 清理临时层 self.ico.ClearLayer() # self.ico.DelLayer(layer_list=temp_layers + [final_tmp_layer] + backup_layers) sys.exit() if name == “main”: app = QApplication(sys.argv) analyzer = chk_Conti_zkline() 在run函数中的删除部分我想要实现:第一:就在备份层阻抗线路删除与temp_toal层touch的整根线路polyline(注意polyline是一根很长线,由很多短的line组成)self.incam.COM(f"sel_polyline_feat,operation=select,x={feature[‘xs’]},y={feature[‘ys’]}")命令能够通过一个坐标点选中一根polyline 第二:删除整根线长小于8的polyline;第三:删除不与背面ball pad导通的polyline; 第四:判断经过删除的备份层是否为空,是与不是都输出messagebox提示并结束整个代码 如果有必要也可改动selectun函数与get_unique_endpoints等其他函数代码
最新发布
11-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值