• [技术干货] Python库中psycopg 和 psycopg2 区别
    psycopg 和 psycopg2 都是用于Python语言连接PostgreSQL数据库的适配器,但实际上,它们之间存在一些区别和联系:版本和历史:psycopg 是指 psycopg 的最新版本,也就是 psycopg3 的简称。psycopg3 是在 psycopg2 之后推出的,它提供了新的特性和改进。psycopg2 是 psycopg 的旧版本,它是一个非常稳定和广泛使用的PostgreSQL适配器,支持Python 2和Python 3。API和用法:psycopg3 提供了一个更加现代和灵活的API,它的设计更加符合Python的编程习惯,例如使用了异步编程支持和类型注解。psycopg2 的API相对较旧,但因为它长时间被广泛使用,因此有着大量的文档和社区支持。性能:psycopg3 在设计上考虑了性能优化,并且引入了一些新的特性来提高性能,例如支持批量操作和复制。psycopg2 虽然稳定,但在某些方面可能不如 psycopg3 性能优越。兼容性:psycopg2 支持Python 2和Python 3,这对于一些老旧的项目来说是非常重要的。psycopg3 主要支持Python 3,不再支持Python 2,这意味着它是面向未来的。维护和支持:由于Python 2已经在2020年停止支持,psycopg2 的维护工作可能会逐渐减少,重点转移到 psycopg3。psycopg3 作为新版本,将获得更长时间的维护和支持。总结来说,如果你正在开始一个新的项目,或者打算升级现有项目以利用最新的特性和性能改进,那么选择 psycopg3 可能是更好的选择。如果你维护的是一个依赖Python 2或者已经使用了 psycopg2 的成熟项目,那么继续使用 psycopg2 可能更为稳妥。在做出选择时,应考虑项目的具体需求和未来发展方向。
  • [技术干货] streamlit @st.cache_data 和 @st.cache_resource 的区别
    streamlit 是一个开源的Python库,用于快速构建数据应用和机器学习模型的原型。在 streamlit 中,@st.cache_data 和 @st.cache_resource 是两种不同的装饰器,它们都用于缓存数据以提高应用的性能,但是它们的使用场景和缓存机制有所不同。以下是 @st.cache_data 和 @st.cache_resource 的主要区别:@st.cache_data目的:用于缓存函数的输出结果,尤其是那些计算成本高的数据或计算结果。存储位置:缓存的 数据存储在内存中。生命周期:当用户的会话结束时,缓存的数据会被清除。适用场景:适用于缓存轻量级的数据,如计算结果、小型数据集等。限制:不应该用于缓存大型数据集或对象,因为这可能会导致内存使用量过大。@st.cache_resource目的:用于缓存资源,如数据库连接、大型数据文件或模型对象,这些资源初始化成本高,且在应用的生命周期内不需要经常改变。存储位置:缓存的资源可以存储在磁盘上,不仅仅限于内存。生命周期:缓存的资源在应用重启之前都会保持缓存状态,不会因为用户会话结束而清除。适用场景:适用于缓存初始化成本高的资源,如数据库连接、大型文件读取、机器学习模型等。限制:由于资源缓存不会在用户会话结束时清除,因此使用时需要确保不会造成资源泄露或不必要的磁盘空间占用。使用建议当你需要缓存的数据是轻量级的,并且生命周期与用户会话相同,使用 @st.cache_data。当你需要缓存的是初始化成本高的资源,并且这些资源在应用重启前不需要改变,使用 @st.cache_resource。正确使用这些装饰器可以显著提高 streamlit 应用的性能,但也要注意不要滥用,以避免造成内存或磁盘空间的浪费。
  • [专题汇总] 2024的尾声,12月份干货合集。
     大家好,首先祝大家新年快乐,身体健康,代码没bug,投产顺利。本次整理带来的有关于mybatis,java,spring,springboot,linux,shell,Python,HarmonyOS,算法等多种类技术干货,希望可以帮到大家。  1.MyBatis 探秘之#{} 与 ${} 参传差异解码(数据库连接池筑牢数据交互根基)【转】 https://bbs.huaweicloud.com/forum/thread-0296171007849327168-1-1.html  2.scala中正则表达式的使用详解【转】 https://bbs.huaweicloud.com/forum/thread-02119171007725887139-1-1.html  3.SpringBoot实现websocket服务端及客户端的详细过程【转】 https://bbs.huaweicloud.com/forum/thread-0217171007411153148-1-1.html  4.spring 参数校验Validation示例详解【转】 https://bbs.huaweicloud.com/forum/thread-02109171007351771185-1-1.html  5.java集成kafka实例代码【转】 https://bbs.huaweicloud.com/forum/thread-02112171007196458168-1-1.html  6.SpringBoot中Get请求和POST请求接收参数示例详解【转】 https://bbs.huaweicloud.com/forum/thread-02112171007106397167-1-1.html  7.Java中StopWatch工具类的用法详解【转】 https://bbs.huaweicloud.com/forum/thread-0263171006880471176-1-1.html  8.Linux下shell基本命令之grep用法及示例小结【转】 https://bbs.huaweicloud.com/forum/thread-02119170989547937131-1-1.html  9.Python使用PIL库拼接图片的详细教程【转】 https://bbs.huaweicloud.com/forum/thread-02119170989479126130-1-1.html  10.bash shell的条件语句详解【转】 https://bbs.huaweicloud.com/forum/thread-0217170989387999141-1-1.html  11.pandas数据缺失的两种处理办法【转】 https://bbs.huaweicloud.com/forum/thread-02112170989326183158-1-1.html  12.Python使用PyQt5实现中英文切换功能【转】 https://bbs.huaweicloud.com/forum/thread-0263170989204908173-1-1.html  13.python螺旋数字矩阵的实现示例【转】 https://bbs.huaweicloud.com/forum/thread-0241170989116650156-1-1.html  14.使用Python实现文件查重功能【转】 https://bbs.huaweicloud.com/forum/thread-02109170989032191180-1-1.html  15.Linux内核验证套件(LKVS) https://bbs.huaweicloud.com/forum/thread-0217170613884758126-1-1.html  16.三大排序算法:插入排序、希尔排序、选择排序 https://bbs.huaweicloud.com/forum/thread-0263170613042983158-1-1.html  17.【Linux】多用户协作-转载 https://bbs.huaweicloud.com/forum/thread-02109170612919963145-1-1.html  18.SSH可以连接但sftp确无法链接,有可能是防火墙的问题吗-转载 https://bbs.huaweicloud.com/forum/thread-0217170612856550125-1-1.html  19.【Linux】线程同步与互斥 (生产者消费者模型-转载 https://bbs.huaweicloud.com/forum/thread-02112170612824528138-1-1.html  20.【HarmonyOS】公司鸿蒙项目收工总结之《组件》 https://bbs.huaweicloud.com/forum/thread-0263170475389496136-1-1.html  21.【HarmonyOS】高仿华为阅读翻页 https://bbs.huaweicloud.com/forum/thread-02109170473860592128-1-1.html  22.【HarmonyOS】仿iOS线性渐变实现 https://bbs.huaweicloud.com/forum/thread-0241170473759150128-1-1.html  23.【HarmonyOS】利用emitter封装工具类 https://bbs.huaweicloud.com/forum/thread-0276170473613513148-1-1.html  24.【HarmonyOS】多Toast显示工具类 https://bbs.huaweicloud.com/forum/thread-0217170472563245114-1-1.html  25.【HarmonyOS】头像裁剪圆形遮罩效果实现demo https://bbs.huaweicloud.com/forum/thread-0276170472467118147-1-1.html 
  • [技术干货] Python使用PIL库拼接图片的详细教程【转】
    1. 安装Pillow库首先,你需要确保你的Python环境中安装了Pillow库。如果还没有安装,你可以使用pip来安装:1pip install pillow2. 导入必要的模块在你的Python脚本中,你需要导入Pillow库中的Image模块。这个模块提供了处理图片所需的所有功能。1from PIL import Image3. 定义拼接函数接下来,定义一个函数来拼接两张图片。这个函数将接受两张图片和一个表示拼接方向的参数(水平或垂直)。def concatenate_images(image1, image2, orientation='horizontal'):     if orientation == 'horizontal':         # 水平拼接         new_image = Image.new('RGB', (image1.width + image2.width, image1.height))         new_image.paste(image1, (0, 0))         new_image.paste(image2, (image1.width, 0))     elif orientation == 'vertical':         # 垂直拼接         new_image = Image.new('RGB', (image1.width, image1.height + image2.height))         new_image.paste(image1, (0, 0))         new_image.paste(image2, (0, image1.height))     else:         raise ValueError('Orientation must be "horizontal" or "vertical"')     return new_image 4. 加载图片使用Image.open()方法加载你想要拼接的两张图片。确保你提供的路径是正确的,并且图片文件存在。12image1 = Image.open('path_to_image1.jpg')image2 = Image.open('path_to_image2.jpg')将'path_to_image1.jpg'和'path_to_image2.jpg'替换为你的图片文件的实际路径。5. 拼接图片调用你定义的concatenate_images()函数,传入两张图片和你想要的拼接方向(‘horizontal’或’vertical’)。1concatenated_image = concatenate_images(image1, image2, 'horizontal')  # 或者 'vertical'6. 保存新图片使用save()方法将拼接后的新图片保存到你的文件系统中。1concatenated_image.save('concatenated_image.jpg')将'concatenated_image.jpg'替换为你想要保存的文件名和格式。完整代码示例 from PIL import Image  def concatenate_images(image1, image2, orientation='horizontal'):     if orientation == 'horizontal':         # 水平拼接         new_image = Image.new('RGB', (image1.width + image2.width, image1.height))         new_image.paste(image1, (0, 0))         new_image.paste(image2, (image1.width, 0))     elif orientation == 'vertical':         # 垂直拼接         new_image = Image.new('RGB', (image1.width, image1.height + image2.height))         new_image.paste(image1, (0, 0))         new_image.paste(image2, (0, image1.height))     else:         raise ValueError('Orientation must be "horizontal" or "vertical"')     return new_image  # 加载图片 image1 = Image.open('path_to_image1.jpg') image2 = Image.open('path_to_image2.jpg')  # 拼接图片 concatenated_image = concatenate_images(image1, image2, 'horizontal')  # 或者 'vertical'  # 保存新图片 concatenated_image.save('concatenated_image.jpg') 更复杂的图片拼接当然,我们可以编写一个更复杂的图片拼接函数,该函数不仅可以处理水平和垂直拼接,还可以处理任意数量的图片,并且允许用户指定拼接图片之间的间距以及输出图片的背景颜色。以下是一个更复杂的图片拼接函数示例: from PIL import Image  def concatenate_images(images, orientation='horizontal', spacing=10, bg_color=(255, 255, 255)):     """     拼接图片的函数。      参数:     images (list of PIL.Image.Image): 要拼接的图片列表。     orientation (str): 拼接方向,'horizontal' 表示水平,'vertical' 表示垂直。     spacing (int): 图片之间的间距(像素)。     bg_color (tuple): 输出图片的背景颜色,格式为 (R, G, B)。      返回:     PIL.Image.Image: 拼接后的新图片。     """     if not images:         raise ValueError("图片列表不能为空")      if orientation == 'horizontal':         # 计算拼接后图片的宽度和高度         total_width = sum(img.width for img in images) + (len(images) - 1) * spacing         max_height = max(img.height for img in images)         new_image = Image.new('RGB', (total_width, max_height), bg_color)          # 依次粘贴图片         current_x = 0         for img in images:             new_image.paste(img, (current_x, 0))             current_x += img.width + spacing             # 最后一个图片不需要间距             if current_x == total_width:                 break             current_x -= spacing     elif orientation == 'vertical':         # 计算拼接后图片的宽度和高度         max_width = max(img.width for img in images)         total_height = sum(img.height for img in images) + (len(images) - 1) * spacing         new_image = Image.new('RGB', (max_width, total_height), bg_color)          # 依次粘贴图片         current_y = 0         for img in images:             new_image.paste(img, (0, current_y))             current_y += img.height + spacing             # 最后一个图片不需要间距             if current_y == total_height:                 break             current_y -= spacing     else:         raise ValueError('Orientation must be "horizontal" or "vertical"')      return new_image  # 使用示例 images = [Image.open('path_to_image1.jpg'), Image.open('path_to_image2.jpg'), Image.open('path_to_image3.jpg')] concatenated_image = concatenate_images(images, orientation='horizontal', spacing=20, bg_color=(255, 255, 255)) concatenated_image.save('concatenated_image.jpg') 在这个函数中:支持任意数量的图片:通过传入一个图片列表来拼接任意数量的图片。图片间距:添加了一个 spacing 参数,允许用户指定图片之间的间距。背景颜色:添加了一个 bg_color 参数,允许用户指定输出图片的背景颜色。错误处理:如果传入的图片列表为空,函数将抛出一个 ValueError。请注意,当拼接方向为水平时,计算了所有图片宽度的总和,并加上了图片之间的间距(除了最后一个图片之外)。同样地,当拼接方向为垂直时,计算了所有图片高度的总和,并加上了图片之间的间距。最后,使用 Image.new() 方法创建一个新的空白图片,并使用 paste() 方法将原始图片粘贴到新的图片上。
  • [技术干货] bash shell的条件语句详解【转】
    12~ script% touch if.sh~ script% chmod 755 if.sh1.if-then-fi1234567#!/usr/bin/env bashFOOD=$1if [ $FOOD="apple" ]then    echo The food is $FOODfiexit 012~ script % ./if.sh appleThe food is apple如果要将多条语句写在一行,可以分号分割开,如:1if [ $FOOD="apple" ];then注意:if [ 条件 ],中括号包住的条件与括号之间必须要有空格。if关键字与中括号之间也必须要有空格。为什么会这样, 因为命令与参数之间必须要用空格分开。[]中括号代表的量test这个命令,所以上面的if语句也可以写成:1234if test $FOOD="apple"then        echo The food is $FOODfi所以如果没有空格了,解析器就会找到一个错误或不存在的命令,因为它会把在每一行遇到的第一个空格前面有字符串的字符串当作是命令,之后的当作是参数。所以如果if和[]没有空格,执行脚本时就会报错,把if[ apple=apple ]都当作是命令了,而这实际上是一个不存在的命令:12~ script % ./if.sh apple./if.sh: line 4: if[ apple=apple ]: command not found温馨提示:赋值语句的等号左右不能有空格,否则会报错。2.else子句if.sh:123456789#!/usr/bin/env bashNUM=$1if [ $NUM -eq 10 ] # = 等价于-eq,后者只能用于数字的比较上,前者=,则在字符串和数字上都能用于相等的比较then        echo it is 10else        echo it is not 10fiexit 012~ script % ./if.sh 109it is not 103.elif子句123456789101112131415#!/usr/bin/env bashNUM=$1if [ $NUM -eq 10 ] # = 等于-eq,后者只能用于数字的比较上,前者则都可以用在字符串和数字的相等比较上then        echo equal 10elif [ $NUM -lt 10 ]then        echo less than 10elif [ $NUM -le 11 ]then        echo less than or equal 11else        echo greater than 11fiexit 012~ script % ./if.sh 109greater than 11-eq:equal 等于-lt:less than 小于-gt:greater than 大于-le:less than or equal 小于或等于-ge:greater than or equal 大于或等于为什么不可以用<,>等来表达上面这些关系,因为这些符号在类Unix系统中有特殊用途。
  • [技术干货] pandas数据缺失的两种处理办法【转】
    数据缺失通常有两种情况:空,None等,在pandas是NAN(和np的nan一样)另一种就是01.为NaN数据的处理1.判断这列有没有NaN12has_nan = df['age'].isnull().any()print(has_nan)或者直接在控制台根据数据进行判断处理方式1:只考虑单列1df2 = df[pd.notnull(df["original_publication_year"]) 这行代码的目的是 去除 original_publication_year 列中含有 NaN 值的行,并生成一个新的 DataFrame(df2),包含了所有 original_publication_year 列中不含 NaN 值的行。3. df["original_publication_year"] 是获取 df 数据框中的 original_publication_year 这一列。4. pd.notnull(df["original_publication_year")用于检查数据中的每个元素是否不是 NaN。返回一个布尔值的 Series.True 的行会被保留;False 的行会被排除(Book2何Book4被去除)。5. 返回一个所有 original_publication_year 列中不是NaN 的行新的DataFrame处理方式2:删除NaN所在的行1dropna(axis=0,how='any',inplace=False)any表示有就删,all表示全部是NaN才删inplace表示是否进行原地修改处理方式3:填充数据12mean_value = df["original_publication_year"].mean()  # 计算均值df_filled=df["original_publication_year"].fillna(mean_value)12345t.fillna(t.mean()) #填充均值t["列名"]=t["列名"].fillna(t["列名"].mean())#单独对某一列进行操作t.fiallna(t.median()) #填充中值t.fillna(0)2:为0数据的处理123t[t==0]=np.nan # 赋值为NaN# 当然并不是每次为0的数据都需要处理# 计算平均值等情况,nan是不参与计算的,但是0会的设置成NaN后用处理NaN的方法处理。
  • [技术干货] Python使用PyQt5实现中英文切换功能【转】
    一、UI界面多语言切换安装必要的工具和库确保你已经安装了PyQt5及其相关工具,如Qt Designer、Qt Linguist等。这些工具通常随PyQt5的安装包一起提供。设计UI界面使用Qt Designer设计你的UI界面,并保存为.ui文件。例如,可以设计一个包含按钮和标签的简单界面。将UI文件转换为Python代码使用pyuic5工具将.ui文件转换为Python代码。例如,如果你的UI文件名为main_window.ui,可以使用以下命令进行转换:pyuic5 -o main_window_ui.py main_window.ui 生成翻译文件使用pylupdate5工具生成翻译文件(.ts文件)。这个文件包含了UI界面中所有需要翻译的字符串。例如:1pylupdate5 main_window_ui.py -ts main_window_en.ts这将生成一个名为main_window_en.ts的英文翻译文件。翻译字符串使用Qt Linguist打开.ts文件,并逐条翻译其中的字符串。翻译完成后,保存并发布翻译文件,这将生成一个.qm文件,该文件是PyQt5实际使用的翻译文件。加载翻译文件在你的Python代码中,使用QTranslator类加载翻译文件,并应用到应用程序中。例如: from PyQt5.QtCore import QTranslator, QCoreApplication from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton import sys  class MainWindow(QMainWindow, Ui_MainWindow):     def __init__(self):         super(MainWindow, self).__init__()         self.setupUi(self)          # 创建QTranslator对象         self.translator = QTranslator()          # 加载翻译文件         # 注意:这里需要根据实际路径来加载.qm文件         self.translator.load(':/translations/main_window_en')  # 假设.qm文件已经被添加到资源文件中          # 安装翻译器到应用程序         QCoreApplication.installTranslator(self.translator)          # 更新UI界面的语言         self.retranslateUi(self)      def retranslateUi(self, MainWindow):         _translate = QCoreApplication.translate         MainWindow.setWindowTitle(_translate("MainWindow", "Main Window"))         # ... 其他需要翻译的字符串  if __name__ == '__main__':     app = QApplication(sys.argv)     mainWindow = MainWindow()     mainWindow.show()     sys.exit(app.exec_()) 注意:在实际应用中,你可能需要根据用户的语言选择来动态加载不同的翻译文件。实现语言切换功能你可以通过按钮或其他控件来实现语言切换功能。在切换语言时,需要卸载当前的翻译器并加载新的翻译器。例如: def switch_to_chinese(self):     # 卸载当前翻译器     QCoreApplication.removeTranslator(self.translator)      # 加载中文翻译文件     self.translator.load(':/translations/main_window_zh_CN')      # 安装新的翻译器到应用程序     QCoreApplication.installTranslator(self.translator)      # 更新UI界面的语言     self.retranslateUi(self)  def switch_to_english(self):     # 类似地,卸载当前翻译器并加载英文翻译文件     # ... 二、程序内部字符串多语言切换对于程序内部的字符串(如日志、错误信息等),你可以使用gettext等国际化工具来实现多语言切换。以下是一个简要的步骤:安装gettext你可以通过pip安装gettext库(如果尚未安装):1pip install gettext但请注意,gettext通常是GNU的一个项目,你可能需要参考其官方文档来获取更详细的信息和安装指南。提取字符串使用xgettext等工具将程序源码中的字符串提取到.po文件中。例如:1xgettext -o messages.po your_script.py --from-code utf-8翻译字符串打开.po文件,并逐条翻译其中的字符串。翻译完成后,保存文件。编译翻译文件使用msgfmt等工具将.po文件编译成.mo文件。例如:12345678910111213import gettextimport os# 设置语言环境目录locale_dir = os.path.join(os.path.dirname(__file__), 'locale')# 根据用户选择的语言加载翻译文件language = 'en'  # 或 'zh_CN' 等t = gettext.translation('messages', localedir=locale_dir, languages=[language])_ = t.gettext# 使用翻译后的字符串print(_("Hello, world!"))
  • [技术干货] python螺旋数字矩阵的实现示例【转】
    python螺旋数字矩阵给出数字个数n (0<n ≤999)和行数m (0<m ≤ 999)。从左上角的1开始,按照顺时针螺旋向内写方式,输出1-n,依次写出2,3.….,最终形成一个m行的矩阵。1.每行数字的个数一样多2.列的数量尽可能少3.填充数字时优先填充外部4.数字不够时,使用单个*号占位 def getRes(n, m):     num_size = n     rows = m      cols, _ = divmod(n, m)     cols = cols + 1 if _ else cols # 列数      res = [['*'] * cols for _ in range(rows)]  # 初始化m行的矩阵     i, j = 0, 0     directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 四个方向依次为:右,下,左,上     direction_index = 0 # 表示当前走的方向,随i和j的变化而变化     for num in range(num_size):         number = num + 1         res[i][j] = str(number)  # 为了后面拼接字符串,所以转str         nxt_i, nxt_j = directions[direction_index][0] + i, directions[direction_index][1] + j  # 按照当前方向时,下一个坐标位置         if not (0 <= nxt_i < rows and 0 <= nxt_j < cols and res[nxt_i][nxt_j] == '*'):# 表示走的方向的改变。当下一个坐标位置出了边界时,或者未到边界但是下一个位置的值不是*,也就是已被填充时,改变方向             direction_index = (direction_index + 1) % 4         i, j = i + directions[direction_index][0], j + directions[direction_index][1]     for values in res:         print('\t'.join(values))  getRes(9, 4) 
  • [技术干货] 使用Python实现文件查重功能【转】
    1.简介这是一个Python文件去重的工具,市面上很多检测重复工具的软件,都是要付费或者要破解的。于是就想着能不能自己做一个后台每时每刻都可以自己去重的工具。虽然市面上很多检测重复工具的软件. 但是这个工具使用环境和那些工具很不一样。 别的工具删重复文件, 都是扫描,自己删除.。需要人工值守.。这边的工具扫描删除不需要人工值守,并且可以后台运行。这边设置好了,就可以吃着火锅唱着歌干别的去了。只要电脑不断电可以一直运行操作。别的软件必须得等扫描完,才能做下一步操作,这个是本质区别。2.工具功能1 通过检测MD5,来判断是否有文件重复,检测过后,可以自行选择删除或者不删除,.或者移动到回收站还是直接删除。2 循环检测指定目录的重复文件,只要是新生成了重复文件,就会立刻被删除。3 删除默认会保留最早的文件。**注:**只要文件属性不一样,即使文件名一样也能查重成功。3.相关源码 import sys, os, filecmp import time from win32com.shell import shell,shellcon   def deltorecyclebin(filename):     #print('deltorecyclebin', filename)     # os.remove(filename) #直接删除文件,不经过回收站     res= shell.SHFileOperation((0,shellcon.FO_DELETE,filename,None, shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION,None,None))  #删除文件到回收站     #print(res)         # if not res[1]:         #     os.system('del '+filename)  #清理重复文件 def md5(fname, chunk_size=1024):     import hashlib     hash = hashlib.md5()     with open(fname, "rb") as f:         chunk = f.read(chunk_size)         while chunk:             hash.update(chunk)             chunk = f.read(chunk_size)     return hash.hexdigest()  def check_for_duplicates(dufilelist):         sizes = {}     hashes = {}     duplicates = []     # Traverse all the files and store their size in a reverse index map     # 遍历所有文件并将其大小存储在反向索引映射中     files_count = 0     #print(dufilelist)     for s in dufilelist:         for root, _dirs, files in os.walk(s, topdown=True, onerror=None, followlinks=False):             files_count += len(files)             for f in files:                 file = os.path.join(root, f)                 size = os.stat(file).st_size                 if size not in sizes:                     sizes[size] = []                 sizes[size].append(file)     #print("Traversed {} files".format(files_count))      # Remove empty files from the size map     # 从大小映射中删除空文件     if 0 in sizes:         del sizes[0]      # Remove files with unique sizes from the size map     # 从大小映射中删除具有唯一大小的文件     for (key, value) in list(sizes.items()):         if len(value) == 1:             del sizes[key]      # Traverse the size map and enrich it with hashes     # 遍历大小映射并用哈希值丰富它     for (size, files) in sizes.items():         for file in files:                         try:                 hash = md5(file)             except:                 continue              tuple = (size, hash)             if tuple not in hashes:                 hashes[tuple] = []             hashes[tuple].append(file)      # Remove files with unique (size, hash) tuple in hash map     # 删除哈希映射中具有唯一(大小,哈希)元组的文件     for (key, value) in list(hashes.items()):         if len(value) == 1:             del hashes[key]      # Compare file pairs     # 比较文件对         for possible_list in hashes.values():         #print(possible_list)         #这里把文件按着时间排序:         if possible_list:             # 注意,这里使用lambda表达式,将文件按照最后修改时间顺序升序排列             # os.path.getmtime() 函数是获取文件最后修改时间             # os.path.getctime() 函数是获取文件最后创建时间             possible_list = sorted(possible_list,key=lambda x: os.path.getctime(x))                   while possible_list:             first = possible_list[0]             copy = [first]             for other in possible_list[1:]:                 if filecmp.cmp(first, other, shallow=False):                     copy.append(other)             for c in copy:                 possible_list.remove(c)             duplicates.append(copy)      #print(duplicates)     # Print duplicates     # 打印相同       groupready=[]     for _i, group in enumerate(duplicates):         print("第 " + str(int(_i) + 1) + " 组")         assert len(group) > 1         #print("%r:" % (i + 1))         if onlyprint:              for d in group:                 pass                 print("发现相同文件:  %r" % (d))             for d in group[1:]:                 groupready.append(d)              #print("全部要删除的文件: "+str(groupready))          else:             if filedelete:                 for d in group[1:]:                     os.remove(d)                     print("直接删除重复文件%r" % (d))             else:                 for d in group[1:]:                     deltorecyclebin(d)                     print("回收重复文件%r" % (d))                       if not duplicates:         print("目录里没有找到重复文件")      if len(groupready)>0:         print("--------------------------------分割线------------------------------------------")         print("下面列出重复的文件:")         for num in groupready:             print(num)          reback=input("输入d直接删除以上的重复文件, ,输入r将以上重复文件放入回收站,,取消请任意输入n或者关闭本窗口.请输入: d/r/n:")         if reback=="d":             for num in groupready:                 os.remove(num)                 print("直接删除重复文件%r" % (num))          elif reback=="r":             for num in groupready:                 deltorecyclebin(num)                 print("回收重复文件%r" % (num))          else:              print("取消操作")     if __name__ == "__main__":             loopinfo=input("是否循环检测重复文件? y/n:")     if loopinfo=="y":         loopinfoable=-1     else:         loopinfoable=1      onlyprintAble=input("只检测重复文件请输入y,检测并且自动删除重复文件请输入n y/n:")     if onlyprintAble=="y":         onlyprint=True        else:         onlyprint=False            filedeleteAble=input("重复文件放入回收站请输入y ,直接删除重复文件请输入n y/n:")         if filedeleteAble=="y":             filedelete=False   #是否强制删除         else:             filedelete=True   #是否强制删除       filepath=input("请输入要检测重复文件的目录:")          time_start=time.time()      while loopinfoable:          loopinfoable=loopinfoable-1                              print("程序开始...请等待一会...我正在努力为主人干活中o(´^`)o...")         dufilelist=[filepath]             check_for_duplicates(dufilelist)                   #下面是计算时间         time_end=time.time()         seconds=time_end-time_start         m, s = divmod(seconds, 60)         h, m = divmod(m, 60)         print('当前程序总共用时:%02d:%02d:%02d' % (h, m, s))                 if loopinfoable!=0: #不循环             time.sleep(3)      input("程序结束,按回车退出") 
  • [问题求助] 第十八期-提交问题
    按照要求把 solution.py和自定义的helper.py打包后,提交显示“missing entry file”;后直接压缩提供的SDK中的solution.py为solution.py.zip提交,仍然显示“missing entry file”,这是为什么?官方提供给你的SDK都有问题?
  • [技术干货] fastapi实现常用接口
    在HTTP协议中,除了GET和POST请求之外,还有多种其他类型的HTTP请求方法,每种方法都有其特定的用途和语义。常见的HTTP请求方法包括:GET:请求从服务器获取资源。POST:向服务器提交数据,通常用于提交表单或上传文件。PUT:向服务器上传或更新资源,通常用于创建或更新资源。DELETE:请求服务器删除资源。PATCH:对资源进行部分更新。HEAD:类似于GET请求,但只返回响应头,不返回响应体。OPTIONS:请求服务器返回该资源所支持的HTTP请求方法的列表。TRACE:沿着到目标资源的路径,将请求和响应返回给客户端(主要用于测试和诊断)。CONNECT:将请求连接转换为透明的TCP/IP隧道(通常用于HTTPS代理)。在FastAPI中,你可以很方便地定义这些不同的HTTP方法。下面是一个简单的例子,展示如何用FastAPI实现这些接口:from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI() # 示例数据模型 class Item(BaseModel): name: str description: str | None = None price: float tax: float | None = None # 初始化一个示例数据库(字典) fake_items_db = {} # GET 请求 @app.get("/items/{item_id}", response_model=Item) async def read_item(item_id: int, q: str = None): item = fake_items_db.get(item_id) if item is None: raise HTTPException(status_code=404, detail="Item not found") if q: return {**item, "description": f"{item['description']} (q={q})"} return item # POST 请求 @app.post("/items/", response_model=Item) async def create_item(item: Item): item_id = len(fake_items_db) + 1 fake_items_db[item_id] = item return {"item_id": item_id, **item} # PUT 请求 @app.put("/items/{item_id}", response_model=Item) async def update_item(item_id: int, item: Item): if item_id not in fake_items_db: raise HTTPException(status_code=404, detail="Item not found") fake_items_db[item_id] = item return item # DELETE 请求 @app.delete("/items/{item_id}") async def delete_item(item_id: int): if item_id not in fake_items_db: raise HTTPException(status_code=404, detail="Item not found") del fake_items_db[item_id] return {"result": "success"} # PATCH 请求 @app.patch("/items/{item_id}", response_model=Item) async def patch_item(item_id: int, item: Item): if item_id not in fake_items_db: raise HTTPException(status_code=404, detail="Item not found") update_data = item.dict(exclude_unset=True) fake_items_db[item_id].update(update_data) return fake_items_db[item_id] # HEAD 请求 @app.head("/items/{item_id}") async def read_item_head(item_id: int): item = fake_items_db.get(item_id) if item is None: raise HTTPException(status_code=404, detail="Item not found") # HEAD 请求不需要返回内容,只设置响应头即可 return Response(status_code=200) # OPTIONS 请求 @app.options("/items/") async def read_items_options(): # OPTIONS 请求通常不需要返回复杂的内容,这里只是演示 return {"allow": ["GET", "POST", "OPTIONS"]} # TRACE 请求通常用于测试和诊断,FastAPI 默认不直接支持 TRACE 请求, # 但你可以通过中间件或自定义路由来实现。 # 这里仅展示概念,不实现具体的 TRACE 请求。 # CONNECT 请求通常用于HTTPS代理,不在FastAPI的应用范围内。 # 启动应用 if __name__ == "__main__": import uvicorn uvicorn.run(app, host="127.0.0.1", port=8000)请注意,上述代码中的HEAD请求直接返回了一个空的Response对象,因为HEAD请求不需要返回响应体。对于OPTIONS请求,它返回了允许的HTTP方法列表。而TRACE和CONNECT请求在实际应用中并不常用,且FastAPI默认不直接支持TRACE请求,CONNECT请求通常用于HTTPS代理,不在FastAPI的应用范围内。
  • [技术干货] Python psutil.net_if_addrs
    psutil.net_if_addrs() 是 Python 中 psutil 库的一个函数,它用于获取系统上所有网络接口的地址信息。这个函数返回一个字典,字典的键是网络接口的名称(如 'eth0'、'wlan0'、'Loopback Pseudo-Interface 1' 等),值是一个列表,列表中的每个元素都是一个命名元组(在 Python 3.x 中是一个 namedtuple),包含了关于该接口上某个地址的详细信息。返回的命名元组通常包含以下字段:family: 地址族(socket.AF_INET 表示 IPv4,socket.AF_INET6 表示 IPv6,psutil.AF_LINK 表示链路层地址,如 MAC 地址)。address: 地址本身(对于 IPv4 和 IPv6 是 IP 地址的字符串表示,对于链路层地址是 MAC 地址的字符串表示,格式为 xx:xx:xx:xx:xx:xx)。netmask: 网络掩码(对于 IPv4 和 IPv6 地址,可能是一个字符串表示的掩码,也可能是一个整数表示的掩码长度;对于链路层地址,此字段通常为 None 或不适用)。broadcast: 广播地址(对于 IPv4 地址,可能是一个字符串表示的广播地址;对于 IPv6、链路层地址或其他不支持广播的地址族,此字段通常为 None)。ptp: 点对点地址(对于某些类型的网络接口,如点对点链路,可能有一个与之关联的对等地址;对于大多数网络接口,此字段通常为 None)。需要注意的是,不是所有字段都会在所有地址族或所有网络接口上可用。例如,链路层地址通常没有 netmask、broadcast 和 ptp 字段。示例代码:import psutil import socket # 获取网络接口的地址信息 net_if_addrs = psutil.net_if_addrs() # 遍历并打印每个网络接口的地址信息 for iface, addrs in net_if_addrs.items(): print(f"接口: {iface}") for addr in addrs: print(f" 地址族: {addr.family} ({socket.AF_INET if addr.family == socket.AF_INET else '非IPv4'})") print(f" 地址: {addr.address}") if addr.netmask is not None: print(f" 网络掩码: {addr.netmask}") if addr.broadcast is not None: print(f" 广播地址: {addr.broadcast}") if addr.ptp is not None: print(f" 点对点地址: {addr.ptp}") print()在这个示例中,我使用了 socket 模块来将地址族(family)的整数值转换为更易读的字符串(例如,将 socket.AF_INET 转换为 'IPv4',尽管在这个上下文中我实际上只检查了它是否等于 socket.AF_INET 来决定是否打印 '非IPv4')。然而,请注意,psutil.AF_LINK(用于链路层地址)并不是 socket 模块的一部分,因此你不能直接通过 socket 模块来检查它;在这个例子中,我只是没有为 psutil.AF_LINK 提供特殊的字符串表示。psutil.net_if_addrs() 函数提供的信息对于诊断网络问题、配置网络接口或监控网络状态非常有用。
  • [技术干货] Python psutil.net_io_counters
    psutil.net_io_counters() 是 Python 中 psutil 库的一个函数,它用于获取系统网络接口的输入/输出统计信息。这个函数返回一个命名元组(在 Python 3.x 中是一个 namedtuple),包含了关于网络 I/O 的全局统计信息。返回的命名元组通常包含以下字段:bytes_sent: 发送的字节总数。bytes_recv: 接收的字节总数。packets_sent: 发送的数据包总数。packets_recv: 接收的数据包总数。errin: 接收时发生的错误总数。errout: 发送时发生的错误总数。dropin: 接收时被丢弃的数据包总数(可能不支持所有平台)。dropout: 发送时被丢弃的数据包总数(可能不支持所有平台)。需要注意的是,dropin 和 dropout 字段可能并不在所有平台上都可用,这取决于底层操作系统的支持和 psutil 库的实现。示例代码:import psutil # 获取网络 I/O 统计信息 net_io = psutil.net_io_counters() # 打印网络 I/O 统计信息 print(f"发送字节数: {net_io.bytes_sent}") print(f"接收字节数: {net_io.bytes_recv}") print(f"发送数据包数: {net_io.packets_sent}") print(f"接收数据包数: {net_io.packets_recv}") print(f"接收错误数: {net_io.errin}") print(f"发送错误数: {net_io.errout}") # 如果平台支持,则打印以下字段 try: print(f"接收被丢弃数据包数: {net_io.dropin}") print(f"发送被丢弃数据包数: {net_io.dropout}") except AttributeError: print("当前平台不支持 dropin 和 dropout 字段")psutil.net_io_counters() 函数提供的统计信息对于监控和分析系统的网络活动非常有用。例如,你可以使用这些信息来计算网络吞吐量、检测网络故障或分析网络性能瓶颈。此外,psutil 库还提供了其他与网络相关的函数,如 psutil.net_connections()(用于获取当前系统的网络连接信息)和 psutil.net_if_addrs()(用于获取网络接口的地址信息)。这些函数可以为你提供更详细的网络状态视图。
  • [技术干货] Python psutil.disk_partitions
    psutil.disk_partitions() 是 Python 中 psutil 库的一个函数,它用于检索系统上所有磁盘分区的信息。这个函数返回一个列表,列表中的每个元素都是一个命名元组(在 Python 3.x 中是一个 namedtuple),包含了关于每个磁盘分区的详细信息。返回的命名元组通常包含以下字段:device: 分区对应的设备名(例如 'sda1'、'C:\\' 等)。mountpoint: 分区的挂载点(即文件系统中的路径,例如 '/'、'C:\\Windows' 等)。如果是未挂载的分区,则此字段可能为 None。fstype: 分区的文件系统类型(例如 'ext4'、'ntfs' 等)。如果无法确定文件系统类型,则此字段可能为 ''(空字符串)。opts: 分区的挂载选项(以逗号分隔的字符串)。这通常包含与挂载相关的额外信息,例如是否以只读方式挂载等。但在某些系统上,这个字段可能为空或包含的信息较少。使用 psutil.disk_partitions() 函数可以帮助开发者或系统管理员获取系统上所有磁盘分区的概览,包括它们的设备名、挂载点、文件系统类型和挂载选项等信息。这些信息对于诊断磁盘相关问题、管理存储资源或进行系统备份和恢复等操作非常有用。示例代码:import psutil # 获取所有磁盘分区的信息 partitions = psutil.disk_partitions() # 遍历并打印每个分区的信息 for partition in partitions: print(f"设备: {partition.device}, 挂载点: {partition.mountpoint}, 文件系统类型: {partition.fstype}, 挂载选项: {partition.opts}")请注意,psutil.disk_partitions() 函数返回的信息取决于底层操作系统的支持和 psutil 库的实现。在某些系统上,某些字段可能为空或包含的信息较少。此外,函数返回的列表中的元素顺序没有特定含义,因此不应该依赖于这个顺序来解析或处理数据。
  • [技术干货] Python psutil.disk_io_counters
    psutil.disk_io_counters() 函数是 Python 中 psutil 库的一部分,用于获取系统磁盘 I/O(输入/输出)的统计信息。这个函数返回一个命名元组(在 Python 3.x 中通常是一个 namedtuple),包含了关于磁盘读写操作的多个字段。返回的命名元组通常包含以下字段:read_count: 读取操作的次数。write_count: 写入操作的次数。read_bytes: 读取的字节总数。write_bytes: 写入的字节总数。read_time: 读取操作花费的总时间(以毫秒为单位)。write_time: 写入操作花费的总时间(以毫秒为单位)。weighted_io: 加权 I/O 时间,这是一个综合指标,考虑了 I/O 操作的速率和大小,用于评估磁盘的忙碌程度。此外,psutil.disk_io_counters() 函数还可以接受两个可选参数:perdisk: 如果设置为 True,函数将返回一个字典,其中键是磁盘设备名(如 'sda'、'nvme0n1' 等),值是对应磁盘的 sdiskio 命名元组。这样你就可以获取每个磁盘设备的详细 I/O 统计信息。如果设置为 False(默认值),函数将返回一个表示所有磁盘设备聚合统计数据的单个 sdiskio 命名元组。nowrap: 在某些系统上,磁盘 I/O 统计信息可能会周期性地重置(例如,当系统启动或达到某个计数阈值时)。如果设置为 True,函数将尝试避免这种重置带来的计数突然减少的问题,但请注意,这可能会导致在某些情况下返回的统计数据不准确。如果设置为 False(默认值),函数将直接返回当前读取的统计数据。使用 psutil.disk_io_counters() 函数可以帮助开发者或系统管理员监控系统的磁盘 I/O 活动,以便诊断性能问题、优化磁盘使用或规划存储升级。