import os import sys import subprocess import re import csv from pathlib import Path # --- 配置区 --- # softBV.x 可执行文件的路径,请根据你的实际情况修改 # 使用 Path.home() 来自动获取用户家目录,比 '~' 更可靠 SOFTBV_EXECUTABLE = Path.home() / "tool/softBV-GUI_linux/bin/softBV.x" # 固定的命令参数 MOBILE_ION = "Li" ION_VALENCE = "1" SF_VALUE = "1000" # 输出CSV文件的名称 OUTPUT_CSV_FILE = "conductivity_results.csv" # --- 配置区结束 --- def check_executable(): """检查 softBV.x 文件是否存在且可执行""" if not SOFTBV_EXECUTABLE.is_file(): print(f"错误: 可执行文件未找到: {SOFTBV_EXECUTABLE}") print("请检查脚本中的 SOFTBV_EXECUTABLE 路径是否正确。") sys.exit(1) if not os.access(SOFTBV_EXECUTABLE, os.X_OK): print(f"错误: 文件存在但不可执行: {SOFTBV_EXECUTABLE}") print("请使用 'chmod +x' 命令赋予其执行权限。") sys.exit(1) def parse_conductivity(output_text): """ 从 softBV.x 的输出文本中解析电导率(conductivity)。 使用正则表达式来匹配 'MD: conductivity = ' 格式的行。 """ # 正则表达式解释: # ^ - 匹配行首 # \s* - 匹配任意数量的空白字符 # MD: conductivity - 匹配字面字符串 # \s*=\s* - 匹配等号,前后可以有任意空白 # ([-\d.eE+]+) - 捕获组1: 匹配并捕获一个或多个数字、点、'e'/'E'、'+'/'-' (科学计数法) pattern = re.compile(r"^\s*MD: conductivity\s*=\s*([-\d.eE+]+)", re.MULTILINE) match = pattern.search(output_text) if match: # 返回捕获到的第一个组 (也就是数值部分) return match.group(1) else: # 如果没有找到匹配的行,返回 None return None def main(): """主函数""" # 1. 检查命令行参数 if len(sys.argv) != 2: print(f"用法: python {sys.argv[0]} ") print(f"例如: python {sys.argv[0]} Br") sys.exit(1) target_folder = Path(sys.argv[1]) # 检查目标文件夹是否存在 if not target_folder.is_dir(): print(f"错误: 文件夹 '{target_folder}' 不存在。") sys.exit(1) # 检查 softBV.x 是否配置正确 check_executable() # 2. 查找所有 .cif 文件 cif_files = sorted(list(target_folder.glob("*.cif"))) if not cif_files: print(f"警告: 在文件夹 '{target_folder}' 中没有找到任何 .cif 文件。") return print(f"在 '{target_folder}' 中找到 {len(cif_files)} 个 .cif 文件,开始处理...") results = [] # 用于存储 (文件名, 电导率) # 3. 遍历文件,执行命令并提取数据 for cif_file in cif_files: print(f" -> 正在处理: {cif_file} ...", end="", flush=True) # 构建命令 command = [ str(SOFTBV_EXECUTABLE), "--md", str(cif_file), MOBILE_ION, ION_VALENCE, SF_VALUE ] try: # 执行命令并捕获输出 # capture_output=True 将 stdout 和 stderr 分别捕获 # text=True (或 encoding='utf-8') 将输出解码为字符串 # check=True 如果命令返回非零退出码 (表示错误),则会抛出异常 process_result = subprocess.run( command, capture_output=True, text=True, check=True, timeout=300 # 设置一个超时时间(例如300秒),防止程序卡死 ) # 从标准输出中解析数据 conductivity = parse_conductivity(process_result.stdout) if conductivity is not None: results.append((cif_file.name, conductivity)) print(f" 成功, conductivity = {conductivity}") else: print(" 失败 (无法在输出中找到conductivity)") # 你也可以选择将错误信息记录下来 # results.append((cif_file.name, "Error: Not Found")) except subprocess.CalledProcessError as e: # 命令执行失败 print(f" 失败 (命令执行错误)") print(f" 错误信息: {e.stderr.strip()}") # results.append((cif_file.name, "Error: Execution Failed")) except subprocess.TimeoutExpired: print(f" 失败 (命令执行超时)") # results.append((cif_file.name, "Error: Timeout")) except Exception as e: # 其他未知错误 print(f" 失败 (发生未知错误: {e})") # results.append((cif_file.name, f"Error: {e}")) # 4. 将结果写入CSV文件 if not results: print("没有成功处理任何文件,不生成CSV。") return print(f"\n处理完成,正在将 {len(results)} 条结果写入 {OUTPUT_CSV_FILE} ...") try: with open(OUTPUT_CSV_FILE, 'w', newline='', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) # 写入表头 writer.writerow(['filename', 'conductivity']) # 写入数据 writer.writerows(results) print("CSV文件已成功生成!") except IOError as e: print(f"错误: 无法写入CSV文件: {e}") if __name__ == "__main__": main()