pyautogui操控Acrobat DC pro万能PDF转Word,不丢任何PDF格式样式
为了将PDF转换脚本改为多进程异步处理,我们需要确保每个进程独立操作不同的Acrobat窗口。以下是实现步骤:
实现代码
import os
import pyautogui
import time
import subprocess
import pygetwindow as gw
from multiprocessing import Pooldef convert_pdf(pdf_path):try:acrobat_path = r"D:\software2\adobedc\Adobe\Acrobat DC\Acrobat\Acrobat.exe"output_dir = r"E:\guarantee_pdf_generator1\excel_option" # 输出目录# 生成输出文件名pdf_filename = os.path.basename(pdf_path)output_name = os.path.splitext(pdf_filename)[0] + ".docx"output_path = os.path.join(output_dir, output_name)# 1. 启动Acrobat新实例并打开PDFsubprocess.Popen([acrobat_path, "/n", pdf_path]) # 使用/n参数确保新窗口time.sleep(5) # 等待窗口加载# 2. 获取窗口句柄expected_title = f"{pdf_filename} - Adobe Acrobat"win = Nonemax_retries = 5for _ in range(max_retries):try:wins = gw.getWindowsWithTitle(expected_title)if wins:win = wins[0]win.activate()breaktime.sleep(2)except Exception as e:print(f"Error activating window: {e}")if not win:print(f"窗口激活失败: {pdf_path}")return# 3. 执行导出操作time.sleep(1)pyautogui.hotkey("alt", "f") # 打开文件菜单time.sleep(0.5)pyautogui.press("t") # 选择"导出"time.sleep(0.5)pyautogui.press("w") # 选择"Microsoft Word"time.sleep(2) # 等待保存对话框# 4. 处理保存对话框pyautogui.write(output_path) # 输入完整输出路径time.sleep(0.5)pyautogui.press("enter")# 5. 等待转换完成time.sleep(15)# 6. 关闭窗口win.close()print(f"转换完成: {pdf_path}")except Exception as e:print(f"处理 {pdf_path} 时出错: {str(e)}")if __name__ == '__main__':# PDF文件列表pdf_list = [r"E:\guarantee_pdf_generator1\excel_option\分析报告1.pdf",r"E:\guarantee_pdf_generator1\excel_option\分析报告2.pdf",# 添加更多PDF路径...]# 创建进程池(根据CPU核心数调整)with Pool(processes=min(4, len(pdf_list))) as pool: # 限制最大并行数pool.map(convert_pdf, pdf_list)
关键改进说明
-
多进程架构:
- 使用
multiprocessing.Pool创建进程池 - 每个PDF文件分配独立进程处理
- 通过
processes参数控制最大并行数(示例设为4)
- 使用
-
窗口精准定位:
- 根据文件名构造窗口标题(“文件名.pdf - Adobe Acrobat”)
- 增加窗口激活重试机制(最多重试5次)
- 使用
/n命令行参数确保新窗口打开
-
操作隔离措施:
- 每个进程独立处理自己的文件路径
- 关键操作步骤间增加缓冲等待时间
- 输出文件自动生成唯一路径
-
异常处理增强:
- 添加try-catch捕获全局异常
- 窗口查找失败时的错误处理
- 进程间错误隔离
使用注意事项
-
Acrobat配置要求:
- 需要确认Adobe Acrobat支持多实例运行
- 确保
/n参数有效(不同版本可能参数不同)
-
路径配置:
- 检查Acrobat安装路径是否正确
- 确保输出目录存在且有写入权限
-
性能调优:
- 根据实际硬件调整等待时间
- 通过
processes参数控制并发数量 - 大文件需要适当增加最后的等待时间
-
错误排查:
- 建议先单进程测试确保基本流程
- 观察窗口标题是否与预期一致
- 检查防病毒软件是否拦截自动化操作
帮用户把现有的Python脚本转换成多进程异步处理,可以同时处理多个PDF,而且互不影响。让我仔细看看用户提供的代码,然后思考如何实现这个需求。
首先,用户原来的代码是使用PyAutoGUI和subprocess来启动Adobe Acrobat,打开一个PDF,然后模拟按键操作将其导出为Word文档。现在的目标是将这个流程扩展到能够同时处理多个PDF文件,每个文件的处理都是独立的进程,互不干扰。
首先,我需要了解用户当前代码的执行流程:
-
使用subprocess启动Acrobat并打开指定的PDF。
-
等待2秒让程序加载。
-
尝试通过pygetwindow激活Acrobat窗口,如果失败则用Alt+Tab切换。
-
模拟键盘操作,导出为Word文档。
-
等待转换完成。
现在的问题在于,当同时处理多个PDF时,各个进程之间可能会互相干扰,比如窗口激活错误,键盘输入混乱等。因为PyAutoGUI是全局的输入模拟,不同进程同时操作会相互影响,导致错误。
所以,我需要考虑如何让每个PDF的处理在独立的进程中运行,确保它们的模拟操作不会互相干扰。可能的解决方案是使用多进程(multiprocessing模块),每个进程处理一个PDF文件。
但多进程的问题在于,每个进程可能需要独立的资源,比如每个Acrobat实例。然而,Adobe Acrobat可能不允许同时打开多个实例,或者打开多个实例会导致资源冲突。需要确认这一点。如果Acrobat只能单实例运行,那么多进程同时操作同一个窗口可能会有问题,导致各个进程的按键操作互相干扰。
或者,用户可能希望每个PDF在同一个Acrobat实例中依次处理,但这同样需要同步,无法并行。所以可能需要每个进程启动自己的Acrobat实例,但这样可能会有问题,比如软件是否支持多实例。
假设Acrobat可以同时打开多个实例,或者每个进程能够独立操作不同的窗口,那么可以尝试用多进程来并行处理。
但另一个问题是,PyAutoGUI的屏幕操作是全局的,如果多个进程同时发送按键或鼠标事件,会导致冲突。例如,进程A正在按Alt+F,而进程B同时按其他键,结果可能混乱。所以,直接的多进程处理可能会导致不可预知的行为。
因此,可能需要找到一种方法来隔离各个进程的输入操作,或者确保每个进程在操作时独占系统输入。但这种方法可能比较复杂,或者不可行。
可能的替代方案是,使用不同的用户会话或虚拟环境,但这显然不现实。
另一个思路是,让每个进程处理不同的PDF时,确保它们的操作在时间上是错开的,或者每个进程在处理时能够正确识别并激活自己的Acrobat窗口。但这需要每个Acrobat窗口有唯一的标题,或者能够通过某种方式区分不同的实例。
例如,当打开不同的PDF文件时,Acrobat的窗口标题可能包含文件名。这样,每个进程可以激活对应的窗口,然后执行操作。这样,即使有多个窗口,每个进程只操作自己的那个窗口。
那么,如何确保每个进程激活正确的窗口?
当前代码中使用的是gw.getWindowsWithTitle(“Adobe Acrobat”)[0],这可能会获取到第一个匹配的窗口,如果同时有多个窗口打开,这会导致错误,比如激活错误的窗口。
所以,可能需要改进窗口激活的逻辑,使得每个进程能够根据具体的PDF文件名或者其他标识找到正确的窗口。
例如,当打开一个PDF时,Acrobat的窗口标题通常是“文件名.pdf - Adobe Acrobat”,所以可以构造窗口标题为“分析报告1.pdf - Adobe Acrobat”,然后通过这个标题来激活窗口。
但这样的话,每个进程需要知道自己的PDF文件名对应的窗口标题,从而可以准确找到窗口。这可能需要修改代码,将窗口标题作为参数传递。
所以,步骤可能是:
-
将原来的脚本改写成一个函数,接受PDF路径和输出文件名等参数。
-
使用multiprocessing模块为每个PDF启动一个进程,调用这个函数。
-
在函数内部,确保每个进程能够正确激活对应的Acrobat窗口,避免与其他进程冲突。
但问题在于,当多个Acrobat实例同时运行时,如何确保每个进程操作的窗口是正确的。例如,同时打开多个PDF可能导致窗口标题变化,或者窗口标题可能被截断,导致无法准确匹配。
此外,Acrobat可能默认使用单实例模式,即每次打开新文件都是在同一个窗口中,而不是新开窗口。这会导致多个进程尝试操作同一个窗口,导致混乱。
因此,需要确定Adobe Acrobat是否支持多实例。如果支持,每个PDF在独立的进程中打开,每个进程对应独立的窗口,这样各个进程可以操作各自的窗口。如果不支持,那么多进程可能无法同时操作。
假设Acrobat支持多实例,或者用户允许在单个实例中处理多个文档,但需要确保每个导出操作互不干扰。这可能需要更精确的窗口管理和操作时序控制。
或者,是否可以使用Adobe Acrobat的命令行工具或API来直接导出PDF到Word,而不需要模拟键盘操作?这样会更可靠,也更容易并行处理。
例如,如果Acrobat有命令行选项或COM接口,可以直接调用导出功能,那么可以避免使用PyAutoGUI,这样多进程处理会更稳定。但用户可能需要Adobe的授权或者特定的版本才能使用这些功能。
不过,用户当前的方案是基于模拟按键的,所以可能需要继续沿着这个方向思考。
现在,回到多进程的问题。假设每个进程处理不同的PDF文件,并且每个进程能够正确激活自己的Acrobat窗口。那么,每个进程需要执行以下步骤:
a. 启动Acrobat并打开指定的PDF,可能通过命令行参数。
b. 等待窗口出现,并激活该窗口。
c. 执行导出操作。
关键在于,每个进程需要能够唯一地识别自己打开的Acrobat窗口。例如,窗口标题可能包含PDF的文件名。例如,如果用户打开的是“分析报告1.pdf”,那么窗口标题可能是“分析报告1.pdf - Adobe Acrobat”。这样,在激活窗口时,可以根据这个标题来找到正确的窗口。
因此,在代码中,可以将激活窗口的部分修改为根据PDF文件名来查找窗口标题。例如:
win_title = f"{os.path.basename(pdf_path)} - Adobe Acrobat"
win = gw.getWindowsWithTitle(win_title)[0]
但需要注意,Acrobat的窗口标题可能因版本或设置而不同,需要确认实际的窗口标题格式。或者,可能存在其他标识窗口的方法,例如进程ID。
这可能需要用户先手动测试,打开一个PDF,查看窗口的准确标题,然后调整代码中的匹配规则。
假设窗口标题正确,那么每个进程可以正确找到自己的窗口,从而避免与其他进程冲突。这样,多进程处理才有可能实现。
现在,关于多进程的实现,可以使用Python的multiprocessing模块。例如,将原来的代码封装成一个函数,接受PDF路径等参数,然后使用Pool或者Process来启动多个进程。
例如:
import multiprocessing
def convert_pdf(pdf_path):
原来的代码,修改为处理pdf_path
if name == ‘main’:
pdf_list = [“path1.pdf”, “path2.pdf”, …]
with multiprocessing.Pool() as pool:
pool.map(convert_pdf, pdf_list)
但需要注意的是,每个进程中的操作必须是独立的,不能有共享资源冲突。例如,同时启动多个Acrobat实例,每个处理自己的PDF,并且每个进程的PyAutoGUI操作不会互相干扰。
但如前所述,PyAutoGUI的模拟输入是全局的,如果多个进程同时发送按键事件,会导致冲突。例如,两个进程同时按Alt+F,可能会导致菜单无法正确打开。
因此,这种方法可能不可行,除非各个进程的操作在时间上是完全错开的,或者每个进程在操作时能够确保独占输入焦点。
另一个思路是,使用进程锁(如互斥锁)来确保同一时间只有一个进程在进行模拟操作。但这会降低并行效率,失去多进程的意义。
或者,是否可以找到一种方法,让每个Acrobat窗口在操作时,独立接收输入事件?例如,在激活窗口后,发送的按键事件仅针对该窗口。但PyAutoGUI的按键操作是系统全局的,无法定向到特定窗口。因此,即使窗口被激活,其他进程的按键事件可能会干扰。
这似乎是最大的挑战。例如,进程A激活窗口A,然后开始发送按键,但此时进程B激活窗口B,导致窗口B获得焦点,进程A的后续按键会发送到窗口B,导致错误。
因此,这种情况下,多进程同时进行模拟操作几乎不可行,因为无法保证输入事件的隔离。
可能的解决方案是,每个进程在操作时必须确保自己的窗口处于激活状态,并且在操作期间不被其他进程的窗口激活干扰。这可能需要精确的时间控制和窗口状态检查,但实现起来非常困难,尤其是在多个进程同时运行的情况下。
或者,是否可以串行处理每个PDF,但通过队列等方式管理任务?这虽然不并行,但可以避免冲突。但用户的需求是希望同时处理多个PDF,相互不影响,所以这可能不符合要求。
另一个可能性是,使用不同的虚拟环境或会话,例如每个进程在一个独立的虚拟桌面中运行,但这可能涉及复杂的配置,且PyAutoGUI可能无法跨桌面操作。
综上,基于模拟界面操作的多进程处理可能面临无法克服的并发输入冲突问题,导致不可靠的结果。
因此,可能需要寻找替代方案,避免使用界面自动化,而使用Acrobat的命令行工具或API进行导出操作。
例如,检查Adobe Acrobat是否提供命令行接口,如使用JavaScript或其他方式执行导出操作。例如,Acrobat的JavaScript支持可以通过命令行调用,执行导出操作。例如:
acrobat.exe /s javascript.js
其中javascript.js包含导出为Word的脚本。
如果有这样的方法,那么每个进程可以独立调用命令行工具,处理各自的PDF,而无需模拟键盘操作。这将大大提高可靠性和并行能力。
用户可能需要查阅Adobe Acrobat的文档,了解是否有相关的API或命令行选项可用。
假设存在这样的方法,那么多进程处理将变得简单,因为每个进程只需要调用命令行工具,无需处理窗口激活和模拟输入的问题。
但如果用户的环境必须通过界面操作来实现,那么可能需要重新考虑整个方法。
回到原问题,如果必须使用模拟输入,那么可能需要接受并行处理中的潜在冲突,或者寻找其他方法。
例如,可以将每个PDF的处理放在独立的进程中,但每个进程在操作时添加足够的延迟,以降低并发冲突的概率。但这并不完全可靠,尤其是在处理多个文件时。
或者,使用进程池,限制同时运行的进程数,比如一次只处理一个PDF,这样虽然不并行,但可以避免冲突。但用户明确要求相互不影响的多进程处理。
这可能意味着,目前的方案无法可靠地实现真正的多进程并行处理,而需要采用其他技术手段。
总结目前的思路:
-
将现有代码封装成函数,处理单个PDF。
-
使用multiprocessing模块创建多个进程,每个处理一个PDF。
-
修改窗口激活逻辑,确保每个进程找到正确的窗口。
-
处理并发输入冲突的问题,这可能需要确保每个进程的操作序列在时间上不重叠,或者找到隔离输入的方法。
现在,我需要具体考虑如何修改代码。
首先,将现有代码转换为函数,例如:
def convert_pdf(pdf_path, output_name):
启动Acrobat并打开pdf_path
导出为output_name.docx
其余步骤…
然后,在主程序中,使用multiprocessing.Process或Pool来启动多个进程。
但问题出现在步骤3和4,即窗口激活和模拟输入部分。
可能的改进点:
- 在打开PDF时,Acrobat的窗口标题可能包含文件名,所以每个进程可以根据自己的pdf_path获取窗口标题,然后激活对应的窗口。
例如:
import os
pdf_filename = os.path.basename(pdf_path)
expected_title = f"{pdf_filename} - Adobe Acrobat"
然后,在查找窗口时:
win = gw.getWindowsWithTitle(expected_title)[0]
这可能更精确,避免激活其他进程的窗口。
但需要测试窗口标题是否正确。例如,如果PDF文件名是“分析报告1.pdf”,窗口标题是否为“分析报告1.pdf - Adobe Acrobat”?
这需要用户确认。如果窗口标题不同,可能需要调整匹配逻辑。
此外,当打开多个PDF时,Acrobat可能使用同一窗口,以标签页形式展示,而不是新窗口。这会导致所有PDF在同一个窗口中打开,此时无法并行处理,因为多个进程会操作同一个窗口,导致混乱。
因此,必须确保每次打开PDF都会启动一个新的Acrobat窗口,而不是在现有窗口中打开。这可能需要Acrobat的设置支持,或者在命令行参数中指定打开方式。
例如,某些程序支持命令行参数如“/n”表示新窗口。需要检查Acrobat的命令行参数是否支持这一点。
例如,subprocess.Popen([acrobat_path, “/n”, pdf_path])
如果这样可以在新窗口中打开每个PDF,那么每个进程的窗口是独立的,窗口标题可能包含文件名,从而可以正确激活。
这可能需要查阅Adobe Acrobat的命令行参数文档。
假设存在这样的参数,允许在新窗口中打开PDF,那么每个进程的窗口是独立的,每个进程可以正确找到自己的窗口。
这样,每个进程的步骤将是:
-
使用命令行参数启动Acrobat新窗口,打开指定的PDF。
-
等待窗口加载。
-
根据PDF文件名找到对应的窗口并激活。
-
执行导出操作。
-
关闭窗口或退出Acrobat(可选)。
这样,多个进程可以并行运行,每个操作自己的窗口,而不会互相干扰。
但需要解决以下问题:
-
Acrobat是否支持多窗口模式。
-
如何确保每个新PDF在新窗口中打开。
-
如何正确获取每个窗口的标题以进行激活。
如果这些条件都满足,那么多进程处理是可行的。
另外,模拟输入的部分可能需要更精确的等待和操作,确保在窗口激活后才发送按键。
例如,在激活窗口后,可能需要等待一段时间,让窗口完全获得焦点,再执行后续的按键操作。
此外,可能需要处理Acrobat的版本差异,比如菜单选项的位置变化等。
现在,假设Acrobat支持多窗口,并且可以通过命令行参数在新窗口中打开,那么代码的大致结构如下:
在convert_pdf函数中:
subprocess.Popen([acrobat_path, “/n”, pdf_path]) # 假设/n参数表示新窗口
time.sleep(2) # 等待窗口打开
获取窗口标题
expected_title = f"{os.path.basename(pdf_path)} - Adobe Acrobat"
try:
win = gw.getWindowsWithTitle(expected_title)[0]
win.activate()
except IndexError:
处理窗口未找到的情况
pass
后续的按键操作…
这样,每个进程处理自己的PDF,并在自己的窗口中操作。
但需要测试这个假设是否成立。
另外,导出时的保存对话框可能需要处理文件名和路径。当前的代码中有注释掉的pyautogui.write和press enter部分,可能需要解除注释并调整,确保每个进程保存到不同的文件名。
例如,输出文件名可以根据输入PDF文件名生成,如将“分析报告1.pdf”转换为“分析报告1.docx”。
这样,在函数中,可以自动生成输出文件名,避免冲突。
此外,保存对话框可能需要处理路径存在与否的问题,或者覆盖确认等,这可能需要额外的模拟操作,如按Tab键切换到保存按钮,或者处理可能出现的覆盖提示。
综上,修改后的代码可能如下:
import os
import pyautogui
import time
import subprocess
import pygetwindow as gw
from multiprocessing import Pool
def convert_pdf(pdf_path):
acrobat_path = r"D:\software2\adobedc\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
启动Acrobat并打开PDF,假设使用/n参数在新窗口中打开
subprocess.Popen([acrobat_path, “/n”, pdf_path])
time.sleep(5) # 等待窗口加载,可能需要更长时间
构造预期的窗口标题
pdf_filename = os.path.basename(pdf_path)
expected_title = f"{pdf_filename} - Adobe Acrobat"
激活窗口
max_retries = 5
for _ in range(max_retries):
try:
win = gw.getWindowsWithTitle(expected_title)[0]
win.activate()
break
except IndexError:
time.sleep(2)
else:
print(f"Window not found for {pdf_path}")
return
模拟按键导出为Word
time.sleep(1)
pyautogui.hotkey(“alt”, “f”) # 打开文件菜单
time.sleep(0.5)
pyautogui.press(“t”) # 导出
time.sleep(0.5)
pyautogui.press(“w”) # 选择Word
time.sleep(0.5)
pyautogui.press(“w”) # 确认选择?可能需要调整
处理保存对话框
time.sleep(1)
output_name = os.path.splitext(pdf_filename)[0] + “.docx”
pyautogui.write(output_name)
time.sleep(0.5)
pyautogui.press(“enter”)
等待转换完成
time.sleep(15)
关闭Acrobat窗口
win.close()
if name == ‘main’:
pdf_list = [
r"E:\guarantee_pdf_generator1\excel_option\分析报告1.pdf",
r"E:\guarantee_pdf_generator1\excel_option\分析报告2.pdf",
添加更多PDF路径
]
with Pool(processes=len(pdf_list)) as pool:
pool.map(convert_pdf, pdf_list)
需要注意的问题:
-
Acrobat的命令行参数是否正确,是否支持/n或其他参数来在新窗口中打开文件。需要查阅Adobe的文档,如果不存在这样的参数,可能需要其他方法。
-
窗口标题是否正确,是否包含文件名。例如,某些情况下标题可能被缩短,或者包含其他信息,如“[兼容模式]”等,这会影响匹配。
-
模拟按键的步骤是否与Acrobat的菜单结构一致。例如,按“t”选择导出,之后按“w”选择Word可能需要更多步骤,或者不同版本的菜单结构不同。
-
保存对话框的处理:输入文件名后可能需要确认保存路径,或者处理文件已存在的提示。
-
进程间的干扰:如果多个进程同时发送按键,可能导致混乱。例如,进程A在打开菜单时,进程B发送按键,导致菜单未正确打开。
可能的改进措施:
-
增加每一步操作的延迟,减少冲突的可能性。
-
在关键步骤中添加重试机制,例如如果窗口激活失败,可以重试几次。
-
确保每个进程的输出文件名唯一,避免保存时冲突。
-
关闭每个窗口在转换完成后,避免累积打开的Acrobat窗口。
此外,可能需要测试在多进程环境下,是否真的可以并行处理多个PDF而互不干扰。例如,运行两个进程处理两个PDF,观察是否都能正确导出。
如果测试中发现窗口激活或按键混乱,可能需要考虑其他方法,如使用队列串行处理,或者寻找非GUI的导出方式。
另一个可能的优化是使用线程代替进程,但由于Python的GIL,多线程在CPU密集型任务中可能不是最佳选择。但由于此处主要是I/O等待(如sleep和窗口操作),多线程可能可行。不过,PyAutoGUI的操作可能仍然存在全局冲突的问题,无论是多进程还是多线程。
总之,最终的方案需要基于测试和调整,确保并行处理的可行性。如果无法解决并发输入的问题,可能需要寻找其他导出PDF的方法,例如使用Adobe的API或第三方库。
该方案通过严格的窗口隔离和时间缓冲机制,能够在多数情况下实现可靠的多PDF并行转换。实际使用时建议先进行小规模测试,逐步增加并发量观察系统稳定性。
相关文章:
pyautogui操控Acrobat DC pro万能PDF转Word,不丢任何PDF格式样式
为了将PDF转换脚本改为多进程异步处理,我们需要确保每个进程独立操作不同的Acrobat窗口。以下是实现步骤: 实现代码 import os import pyautogui import time import subprocess import pygetwindow as gw from multiprocessing import Pooldef conver…...
Day32:字符串的复制
在 Python 中,字符串的复制是指创建一个新的字符串,它的内容与原字符串相同。字符串是不可变的对象,这意味着你不能直接修改字符串的内容,但是可以通过复制来创建新的字符串进行操作。字符串的复制在一些情况下非常有用࿰…...
基于Mybatis继承AbstractRoutingDataSource使用自定义注解实现动态数据源
一:实现 方式一:继承AbstractRoutingDataSource使用自定义注解实现 环境:springboot3 MyBatis3 mysql-connector8 DataSourceKeyEnum枚举类 有几个数据源就配置几个枚举类,和数据源数量一一对应 class DataSourceKeyEnum{D…...
ZooKeeper 数据模型
ZooKeeper 数据模型 ZooKeeper 拥有层次化的命名空间,类似分布式文件系统,但每个节点不仅能有子节点,还可关联数据。节点路径为规范的绝对路径,用斜杠分隔,无相对引用。路径命名有如下约束: 路径名不能包…...
【VUE】Vue2中Vue.extend方法
在 Vue.js 2.x 版本中,Vue.extend() 方法被用于创建一个新的 Vue 子类,可以在该子类上扩展一些属性、指令和组件选项等,然后进行实例化。 比如,可以在创建一些类似 loading 式的函数式插件时,使用: 在 Vue…...
MaskGAE论文阅读
What’s Behind the Mask: Understanding Masked Graph Modeling for Graph Autoencoders 碎碎念:一篇论文看四天,效率也没谁了(捂脸) 看一点忘一点,虽然在本子上有记录,但还是忘,下次看一点在博客上记一点启发 本来很…...
Mybatis-plus 更新 Null 的策略踩坑记
一个bug 在一个管理页面,有一个非必填字段被设置成空了并提交更新,再次打开的时候,发现字段还在,并没有被更新成功。 使用的数据库映射框架是 Mybatis-plus ,对于Mybatis 在更新字段的时候会对空进行校验,…...
Oracle迁移DM数据库
Oracle迁移DM数据库 本文记录使用达梦官方数据迁移工具DTS,将Oracle数据库的数据迁移至达梦数据库。 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具,点击新建工程,填写好工程信息,如图: 2.2 新建迁…...
HTML特殊符号的使用示例
目录 一、基本特殊符号的使用 1、空格符号: 2、小于号 和 大于号: 3、引号: 二、版权、注册商标符号的使用 1、版权符号:© 2、注册商标符号: 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...
数据结构基础之《(15)—排序算法小结》
一、排序算法的稳定性 1、稳定性是指同样大小的样本再排序之后不会改变相对次序 2、对基础类型来说,稳定性毫无意义 比如:3和3没有区别。《潜伏》里说同样两个一百元大钞,你能告诉我哪一个是高尚的那一个是龌龊的么 3、对非基础类型来说&a…...
Linux系统下速通stm32的clion开发环境配置
陆陆续续搞这个已经很久了。 因为自己新电脑是linux系统无法使用keil,一开始想使用vscode里的eide但感觉不太好用;后面想直接使用cudeide但又不想妥协,想趁着这个机会把linux上的其他单片机开发配置也搞明白;而且非常想搞懂cmake…...
【2024年 CSDN博客之星】我的2024年创作之旅:从C语言到人工智能,个人成长与突破的全景回顾
我的2024年创作之旅:从C语言到人工智能,个人成长与突破的全景回顾 引言 回望2024年,我不仅收获了技术上的成长,更收获了来自CSDN平台上无数粉丝、朋友以及网友们的支持与鼓励。在这条创作之路上,CSDN不仅是我展示技术成…...
Python 轻松扫描,快速检测:高效IP网段扫描工具全解析
Python 轻松扫描,快速检测:高效IP网段扫描工具全解析 相关资源文件已经打包成EXE文件,可双击直接运行程序,且文章末尾已附上相关源码,以供大家学习交流,博主主页还有更多Python相关程序案例,秉着…...
go入门Windows环境搭建
简介 Go 即 Golang,是 Google 公司 2009 年 11 月正式对外公开的一门编程语言。 根据 Go 语言开发者自述,近 10 多年,从单机时代的 C 语言到现在互联网时代的 Java,都没有令人满意的开发语言,而 C往往给人的感觉是&a…...
安装Ubuntu22.04
1.引用教程 如何安装Ubuntu Server 22.04 LTS_ubuntu22.04 server-CSDN博客 2.空间分配 要使用 docker 比较多所以分别的 docker 空间大...
对比OpenAI的AI智能体Operator和智谱的GLM-PC,它们有哪些不同?
OpenAI 的 AI 智能体 Operator 和智谱的 GLM-PC 有以下不同: 功能侧重 Operator:主要侧重于网页操作,能在网页上模拟人类进行点击、输入等操作,完成如预订旅行住宿、餐厅预约、在线购物、在 Arxiv 上进行论文分类搜索等任务123。…...
Git Bash 配置 zsh
博客食用更佳 博客链接 安装 zsh 安装 Zsh 安装 Oh-my-zsh github仓库 sh -c "$(curl -fsSL https://install.ohmyz.sh/)"让 zsh 成为 git bash 默认终端 vi ~/.bashrc写入: if [ -t 1 ]; thenexec zsh fisource ~/.bashrc再重启即可。 更换主题 …...
美格智能AIMO智能体+DeepSeek-R1模型,AI应用的iPhone时刻来了
导语: 当AI大模型从云端下沉至终端设备,一场关于效率、隐私与智能化的革命悄然展开。作为全球领先的无线通信模组及解决方案提供商,美格智能凭借其高算力AI模组矩阵与端侧大模型部署经验,结合最新发布的AIMO智能体产品࿰…...
Python标准库 - os (1) 环境变量、进程的用户和组
文章目录 1 访问和修改环境变量1.1 访问环境变量1.2 修改环境变量 2 进程的用户和组2.1 进程的ID2.2 进程的用户2.3 进程组 os模块提供了各种操作系统接口。包括环境变量、进程管理、进程调度、文件操作等方面。 这里整理了环境变量、进程的用户和用户组相关的控制方法。 参考…...
QT 通过ODBC连接数据库的好方法:
效果图: PWD使用自己的,我的这是自己的,所以你用不了。 以下是格式。 // 1. 设置数据库连接 QSqlDatabase db QSqlDatabase::addDatabase("QODBC");// 建立和QMYSQL数据库的连接 // 设置数据库连接名称(DSN&am…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
