python - 将目录树遍历与需要在 python 中运行的代码分离
问题描述
我在一个看起来像这样的目录结构中运行模拟rootDir/*pot/*K/*Ang/lambda_*
。星号具有其通常的通配符含义并被各种不同的参数替换。
过去,我们小组使用 bash 完成大多数此类任务,其中使用此类通配符非常简单。但是,我们正在尝试切换到 python,因为它总体上更强大。但是在 python 中,cat *K/file >> newfile
有点糟糕,这意味着通常需要更多的代码。
此外,编写真正需要运行嵌套 5 次循环的关键代码也很糟糕,尤其是当您必须进一步进行更改时。它只是杂乱无章。
所以我写了一个模块,将遍历和代码执行分离得相当不错。优点是我可以为给定的文件夹结构创建一个模板,然后只需添加很少的几行就可以在我想要的任何位置运行不同的代码。但是,它使用了一种你们大多数人会讨厌我的 hack,并且也有问题,因为应该运行的代码实际上是在帮助模块的范围内执行的,所以几乎必须选择从那里运行所有代码,或没有。
这是模块(我称之为“actionChain.py”):
#!/usr/bin/env python3
import os
import shutil
import fnmatch
import re
j = os.path.join
class actionChain:
def __init__(self, path):
self.path = os.path.abspath(path)
self.basename = os.path.basename(self.path)
self.firstCommands = []
self.lastCommands = []
self.actionSteps = []
def setPath(self, path):
self.path = os.path.abspath(path)
self.basename = os.path.basename(self.path)
def addActionSteps(self, *actionSteps):
for step in actionSteps:
self.actionSteps.append(step)
def addFirstCommands(self, *firstCommands):
for command in firstCommands:
self.firstCommands.append(command)
def addLastCommands(self, *lastCommands):
for command in lastCommands:
self.lastCommands.append(command)
def run(self):
currentDir = os.getcwd()
os.chdir(self.path)
for c in self.firstCommands:
exec(c)
# Do not ever repeat this hack unless you know _very_ well what you're doing
globals().update(locals())
if self.actionSteps:
self.actionSteps[0].run(self.actionSteps[1:])
for c in self.lastCommands:
exec(c)
# Do not ever repeat this hack unless you know _very_ well what you're doing
globals().update(locals())
os.chdir(currentDir)
class actionStep:
def __init__(self, pattern):
self.pattern = pattern
self.firstCommands = []
self.lastCommands = []
def setPattern(self, pattern):
self.pattern = pattern
def addFirstCommands(self, *firstCommands):
for command in firstCommands:
self.firstCommands.append(command)
def addLastCommands(self, *lastCommands):
for command in lastCommands:
self.lastCommands.append(command)
def run(self, subsequentSteps):
files = os.listdir(".")
for f in files:
if os.path.isdir(f) and fnmatch.fnmatch(f, self.pattern):
os.chdir(f)
for c in self.firstCommands:
exec(c)
# Do not ever repeat this hack unless you know _very_ well what you're doing
globals().update(locals())
if subsequentSteps:
subsequentSteps[0].run(subsequentSteps[1:])
for c in self.lastCommands:
exec(c)
# Do not ever repeat this hack unless you know _very_ well what you're doing
globals().update(locals())
os.chdir("..")
这很好,因为它允许我使用这样的代码:
#!/usr/bin/env python3
import actionChain as ac
chain = ac.actionChain(".")
rootDir = ac.actionStep("mtp_to_mtp_allVT")
targetDir = ac.actionStep("target_*")
refDir = ac.actionStep("reference_*")
TDir = ac.actionStep("*K")
aLatDir = ac.actionStep("*Ang")
lambdaDir = ac.actionStep("lambda_*")
chain.addActionSteps(rootDir, targetDir, refDir, TDir, aLatDir, lambdaDir)
# Get variables from structure -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-
targetDir.addFirstCommands(r"""
target = re.search('(?<=target_).*', os.path.basename(os.getcwd())).group(0)
print('target:', target)
""")
refDir.addFirstCommands(r"""
ref = re.search('(?<=reference_).*', os.path.basename(os.getcwd())).group(0)
print('ref:', ref)
""")
TDir.addFirstCommands(r"""
T = re.search('.*(?=K)', os.path.basename(os.getcwd())).group(0)
print('T:', T)
""")
aLatDir.addFirstCommands(r"""
aLat = re.search('.*(?=Ang)', os.path.basename(os.getcwd())).group(0)
""")
lambdaDir.addFirstCommands(r"""
l = re.search('(?<=lambda_).*', os.path.basename(os.getcwd())).group(0)
""")
# get variables from structure -^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-
# Your code goes here -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v
chain.addFirstCommands("noAtoms = 125")
refDir.addFirstCommands(r"""
extract = open('extractedData.tsv', 'w')
extract.write('#T[K]\taLat[Ang]\tpotEne[eV]\tpotEneRef[eV]\tpotEne-potEneRef[meV/atom]\n')
""")
refDir.addLastCommands(r"""
extract.close()
""")
lambdaDir.setPattern("lambda_1.00")
lambdaDir.addFirstCommands(r"""
f = open('dUdL', 'r')
line = f.readlines()[1].split()
f.close
potEne = line[9]
potEneRef = line[10]
extract.write('{}\t{}\t{}\t{}\t{}\n'.format(T, aLat, potEne, potEneRef, (float(potEne)-float(potEneRef))/noAtoms))
""")
# Your code goes here -^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-
chain.run()
如您所见,这些字符串代码中的语法高亮也是一个问题。
我意识到这是一个相当广泛的问题,但是您对如何更好地解决这个问题有什么建议吗?少hacky?还是比较简单易用?
这些是我需要修复的东西:
- “执行代码”必须在我的实际脚本范围内运行,这样它才能与没有通过“actionChain”运行的代码进行交互
- 我希望有工作语法突出显示
- 没有肮脏的黑客,但实际上是安全和正确的代码
- 仍然尽可能多地分离遍历和“做事”
解决方案
推荐阅读
- javascript - 使用 childNodes 检查类并通过 javascript 获取属性
- javascript - 正则表达式 - 获取 > 和 < 之间的所有文本,但如果介于 > 之间则不获取文本
我在试图找出这个正则表达式代码时遇到问题。让我展示一下代码,然后再解释一下。
<div class="test"> Nisl rhoncus mattis rhoncus urna neque viverra. Senectus et netus et malesuada. <
- javascript - 功能组件的哪些部分在重新渲染时运行?
- wpf - 我想重新排列自然完成的 ObservableCollection
- css - 我想以角度构建像这样的 Mat stepper
- php - 在高级自定义字段中使用时间间隔填充选择字段
- django - 我应该在模板化的登录表单中使用操作吗?
- android - android.view.InflateException:二进制 XML 文件第 119 行:膨胀类 com.google.android.material.textview.MaterialTextView 时出错
- reactjs - 所见即所得编辑器无法在编辑器框中显示图像?
- javascript - 如何根据 React Material Ui 中其他文本字段的输入来验证文本字段?