当前在初创芯片公司,工作中经常需要通过脚本实现效率提升。因为公司人少,都需要自己空闲时间做一些脚本。最近使用AI做了两个尝试,明显能感觉到AI带给我的效率提升。以前是我需要自己梳理需求、写代码、调试。现在用上AI,我只需要自己提需求,然后迭代需求,测试和微调脚本即可。而且在使用AI的时候,也领会到一点和AI打交道的方法。
先介绍一下两个脚本的用途,最后会贴上可以使用的脚本代码。
脚本1:文件列表展开工具,命令行方式运行。因为芯片编译的filelist经常是嵌套的,且带环境变量的,但是有些工具(例如FPGA编译工具)需要读取打平的filelist。
脚本2:excel反标工具,带图形界面。在芯片开发末期,要做一些质量活动——就是确认下游是否覆盖了上游的需求,例如验证是否覆盖所有设计的功能点。经常需要在设计的功能点(excel文件A)上标注对应验证的测试点(excel文件B)的编号,这个工作就是需要从文件B中复制测试点编号的单元格内容,到文件A中。过程中有大量的ctrl+c和ctrl+v的操作,每次做下来,左手累的不行。希望有个脚本能实现ctrl+c和ctrl+v的动作。
1、文件列表展开脚本
要处理的文件层级如下:
顶层的filelist如下:
子级filelist内容如下:
AI提示词V1.0:
帮我写一个python脚本。工作环境为linux。filest文件中每一行是一个文件路径,把其中的环境变量展开,然后输出为一个新的文件。filelist中还会嵌套filelist,也需要展开。filelist的行前缀-f。删除文件路径两侧的空格。
生成的代码V1.0:
import os
def expand_env_variables(path):
"""展开环境变量"""
return os.path.expandvars(path)
def process_file_list(file_list_path, output_path):
"""处理文件列表,展开环境变量,并输出到新文件"""
expanded_paths = []
with open(file_list_path, 'r') as file:
for line in file:
# 删除行首尾的空格
line = line.strip()
# 检查是否是文件列表的行
if line.startswith('-f'):
# 递归处理嵌套的filelist
nested_file_list_path = expand_env_variables(line[2:])
nested_paths = process_file_list(nested_file_list_path, output_path)
expanded_paths.extend(nested_paths)
else:
# 展开环境变量并添加到列表
expanded_path = expand_env_variables(line)
expanded_paths.append(expanded_path)
# 将展开后的路径写入到输出文件
with open(output_path, 'w') as output_file:
for path in expanded_paths:
output_file.write(path + '\n')
# 脚本的入口点
if __name__ == "__main__":
file_list_path = 'filelist' # 假设你的文件名为filelist
output_file_path = 'expanded_filelist' # 输出文件的名称
process_file_list(file_list_path, output_file_path)
这个脚本有3个问题:
1、就是process_file_list每次调用都会打开文件。但是递归调用的时候,写入有些问题
2、嵌套的filelist路径还会包含空格,会出错。看来去掉空格这个命令,AI理解的和我不同。
3、只处理嵌套的filelist,而且递归调用处理二级fielist时,会返回空(因为只处理前缀-f的行),导致运行出错。
AI提示词V2.0
帮我写一个python脚本。工作环境为linux。filest文件中每一行是一个文件路径,把其中的环境变量展开,然后输出为一个新的文件。filelist中还会嵌套filelist,也需要展开。filelist中嵌套的filelist的行前缀-f,其他的文件没有前缀。删除文件路径两侧的空格。文件路径提取后先保存在一个列表中,读取完成后,再一次性输出到文件。递归执行时,返回列表,不要直接写入文件。先把路径两侧可能存在的空格去掉,再展开环境变量。
生成的代码V2.0
import os
def expand_path(path):
# 去除路径两侧的空格并展开环境变量
return os.path.expandvars(os.path.expanduser(path.strip()))
def process_filelist(filelist_path, expanded_paths):
# 读取filelist文件
with open(filelist_path, 'r') as file:
for line in file:
original_line = line
# 去除行首尾的空格
stripped_line = line.strip()
# 检查是否是嵌套的filelist文件
if stripped_line.startswith('-f'):
# 去除'-f'前缀并处理嵌套的filelist
nested_filelist_path = expand_path(stripped_line[2:])
if os.path.isfile(nested_filelist_path):
# 递归处理嵌套的filelist文件
process_filelist(nested_filelist_path, expanded_paths)
else:
# 展开环境变量
expanded_path = expand_path(stripped_line)
# 确保路径是文件并且存在,避免重复添加
if os.path.isfile(expanded_path) and expanded_path not in expanded_paths:
expanded_paths.append(expanded_path)
return expanded_paths
def main():
# filelist文件的路径
filelist_path = 'filelist'
# 用于存储所有文件路径的列表
expanded_paths = []
# 处理filelist文件并获取所有路径
expanded_paths = process_filelist(filelist_path, expanded_paths)
# 将路径列表写入到新文件
with open('expanded_file_paths.txt', 'w') as output_file:
for path in expanded_paths:
output_file.write(path + '\n')
print(f"Expanded paths have been written to 'expanded_file_paths.txt'")
if __name__ == "__main__":
main()
运行结果
2、excel反标工具
由于生成的代码比较长,我就每个都贴了。只是贴一下提示词,以及生成的脚本的缺点。
提示词V1.0
帮我写一个python脚本。使用pywin32和pyside6。需求如下:1、支持从当前已经打开的excel文件中选择excel文件;2、支持提取两个excel文件中选中的单元格的内容;3、提供界面,界面有2个下拉菜单,下拉菜单中为当前打开的excel文件名,支持从其中选择excel文件;还需要一个刷新按钮,更新下拉菜单; 4、支持界面置顶显示,也可以取消置顶显示,置顶选择按钮按下表示置顶,弹起表示取消置顶;5、支持通过一个按键(颜色为蓝色),关联两个单元格的内容——关联方式为,将其中一个文件单元格拷贝另一个文件的同一行的某列,列的位置,可以通过界面下拉菜单选择。6、界面有一个刷新按钮,用于更新excel文件列表。7、界面还支持一个按钮来表示复制的方向,按钮弹起时,表示从第一个文件复制到第二个文件的某个单元格,按键按下时表示从第二个文件复制到第一个文件的某个单元格,此单元格与excel中已选中的单元格同行,列的位置由界面选择的列位置来决定。
生成的GUI界面:
问题:可以生成图形界面每个按钮有对应的调用函数,但是调用函数里面只有一些打印提示,没有对应的功能(虽然我在提示词中对每个按钮的功能有描述,但是AI看起来只理解到对界面的诉求,没有理解按钮背后要做的动作。
提示词V2.0
提示词改进点:增加功能需求概述,放在提示词最前面;对界面显示区域进行划分。
帮我写一个python脚本。使用pywin32和pyside6。脚本支持从当前已经打开的excel文件中选择excel文件,支持复制其中一个excel文件中选中的单元格的内容,粘贴到另外一个excel选中的单元格中;脚本还支持界面。
脚本的界面需要分3个区域。
区域1包含如下控件:静态文本,内容为”Excel文件1”,按照最小长度显示;下拉菜单A,显示当前已经打开的excel的文件名,下拉菜单通过“更新”按钮刷新下拉选项。
区域2包含如下控件:静态文本,内容为”Excel文件2”,按照最小长度显示;下拉菜单A,显示当前已经打开的excel的文件名,下拉菜单通过“更新”按钮刷新下拉选项。
区域3包含控件:刷新按钮,按钮按下时,重新检测已经打开的excel文件,更新区域1和2中的下拉菜单,刷新前保留之前选中的文件名,更新下来菜单后,如果之前下拉菜单的选中的文件还在下来选项中,则还是选择和之前一样的文件名;方向按钮,弹起时表示从区域1的菜单A中选中的单元格,复制到区域2的菜单A文件当前激活的sheet的单元格,按下时,则相反,按钮支持check;关联按钮,无需check,填充浅蓝色,此按钮按下时,按照方向按钮的选择,将选中的单元格复制到另一个excel文件选中的单元格;置顶按钮,有check功能,按下时,表示置顶,此按钮填充为黄色,弹起时表示不置顶,无填充,默认为置顶。
运行效果:
生成的脚本还是有一点问题,修改后可以使用的代码如下:
import sys
import win32com.client
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QComboBox, QPushButton, QCheckBox)
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QShortcut, QKeySequence
import os
class ExcelManager(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.direction = 'to2' # 'to1' or 'to2'
def initUI(self):
# 设置窗口标题和初始大小
self.setWindowTitle('Excel Manager')
self.setGeometry(100, 100, 800, 200)
# 创建垂直布局
layout = QVBoxLayout(self)
# 区域1
self.region1_layout = QHBoxLayout()
self.label1 = QLabel('Excel文件1')
self.label1.setMinimumWidth(self.label1.sizeHint().width())
self.comboBoxA1 = QComboBox()
self.region1_layout.addWidget(self.label1)
self.region1_layout.addWidget(self.comboBoxA1, stretch=5)
layout.addLayout(self.region1_layout)
# 区域2
self.region2_layout = QHBoxLayout()
self.label2 = QLabel('Excel文件2')
self.label2.setMinimumWidth(self.label2.sizeHint().width())
self.comboBoxA2 = QComboBox()
self.region2_layout.addWidget(self.label2)
self.region2_layout.addWidget(self.comboBoxA2, stretch=5)
layout.addLayout(self.region2_layout)
# 区域3
self.region3_layout = QHBoxLayout()
self.refreshButton = QPushButton('刷新')
self.directionButton = QPushButton('方向:1-->2')
self.directionButton.setCheckable(True)
self.assocButton = QPushButton('关联')
self.assocButton.setStyleSheet("background-color: lightblue")
self.stickyButton = QCheckBox('置顶')
self.region3_layout.addWidget(self.refreshButton)
self.region3_layout.addWidget(self.directionButton)
self.region3_layout.addWidget(self.assocButton)
self.region3_layout.addWidget(self.stickyButton)
layout.addLayout(self.region3_layout)
# # 创建一个全局快捷键 F4
# self.shortcut = QShortcut(QKeySequence(Qt.Key_F4), self, context=Qt.ApplicationShortcut)
# self.shortcut.activated.connect(self.copy_cells)
# 连接信号和槽
self.refreshButton.clicked.connect(self.refresh_comboboxes)
self.directionButton.clicked.connect(self.toggle_direction)
self.assocButton.clicked.connect(self.copy_cells)
self.stickyButton.stateChanged.connect(self.sticky_logic)
self.stickyButton.setChecked(True) # 默认选中
# 刷新下拉菜单
self.refresh_comboboxes()
# 设置下拉菜单的默认值
def refresh_comboboxes(self):
# 使用pywin32获取打开的Excel文件列表
app = win32com.client.Dispatch("Excel.Application")
excel_files = []
try:
for book in app.Workbooks:
excel_files.append(book.FullName)
except (IndexError, AttributeError):
pass
current_selection1 = self.comboBoxA1.currentText()
current_selection2 = self.comboBoxA2.currentText()
self.comboBoxA1.clear()
self.comboBoxA2.clear()
self.comboBoxA1.addItems(excel_files)
self.comboBoxA2.addItems(excel_files)
if current_selection1 in excel_files:
self.comboBoxA1.setCurrentText(current_selection1)
if current_selection2 in excel_files:
self.comboBoxA2.setCurrentText(current_selection2)
def toggle_direction(self):
# 切换方向
if self.direction == 'to2' :
self.direction = 'to1'
self.directionButton.setText('方向:文件1<--2')
else:
self.direction = 'to2'
self.directionButton.setText('方向:文件1-->2')
print(f"方向已切换到: {self.direction}")
def copy_cells(self):
# 复制单元格内容
if self.comboBoxA1.currentIndex() == -1 or self.comboBoxA2.currentIndex() == -1:
print("请先选择两个Excel文件")
return
if(self.comboBoxA1.currentText() == self.comboBoxA2.currentText()):
print("请先选择两个不同的Excel文件")
return
xls_app = win32com.client.Dispatch("Excel.Application")
original_display_alerts = xls_app.DisplayAlerts # 保存原始状态
# # 关闭警告,以便在操作过程中不显示任何对话框
# xls_app.DisplayAlerts = False
comboBoxA1_filename = os.path.basename(self.comboBoxA1.currentText())
comboBoxA2_filename = os.path.basename(self.comboBoxA2.currentText())
for wb in xls_app.Workbooks:
if(wb.Name == comboBoxA1_filename):
wb1=wb
if(wb.Name == comboBoxA2_filename):
wb2 = wb
try:
if self.direction == 'to2':
wb1.Activate()
selected_range1 = wb1.Application.Selection
value1 = selected_range1.Value
wb2.Activate()
selected_range2 = wb2.Application.Selection
if(selected_range2.Text != ""):
selected_range2.Value +='\n'+ value1
else:
selected_range2.Value = value1
# print(wb1.Name, selected_range1.Row, selected_range1.Column, value1)
# print(wb2.Name, selected_range2.Row, selected_range2.Column, selected_range2.Value)
# print('\n')
else:
wb2.Activate()
selected_range2 = wb2.Application.Selection
value2 = selected_range2.Value
wb1.Activate()
selected_range1 = wb1.Application.Selection
if(selected_range1.Text != ""):
selected_range1.Value +='\n'+ value2
else:
selected_range1.Value = value2
except Exception as e:
print(f"复制出错: {e}")
# finally:
# excel1.Close(SaveChanges=False)
# excel2.Close(SaveChanges=False)
def sticky_logic(self, state):
if state == Qt.Checked:
self.stickyButton.setStyleSheet("background-color: yellow")
self.setWindowFlags(Qt.WindowStaysOnTopHint)
else:
self.stickyButton.setStyleSheet("")
self.setWindowFlags(Qt.Window)
self.show()
def main():
app = QApplication(sys.argv)
excel_manager = ExcelManager()
excel_manager.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()
copy_cells函数调整过,和我想要的有差异。但是感觉文字不好描述。
3、总结
避免错误的提示词
filelist的提示词中的
先把路径两侧可能存在的空格去掉,再展开环境变量。
我也是试过另一个错误的表述:
替换环境变量前,先去掉路径的空格
这个“前”被AI理解为位置关系,而不是操作顺序关系。
推荐使用总分结构组织提示词
建议使用总分结构。就是先描述整体的功能,然后再描述细分的功能。只描述细节的功能,感觉AI就像一个新同事一样,不知道你在说什么。先要给它一个概括的描述,然后再层层展开。
效率提升效果
首先,我自己经常使用pywin32来操作excel,对于这个库比较熟悉,所以改起来就很快。如果你对这个库一无所知,AI还很难一次做对。
但是对于第二个脚本一共接近180行,如果我自己写、调试至少需要1天的时间。但是用AI生成,我自己只是改脚本,就变得轻松狠多。
所以AI对于有一定编程经验(但不需要达到高手的水平)的人来说,提升效果很明显。
版权归原作者 flashman911 所有, 如有侵权,请联系我们删除。