Python递归树示例
我正在分析一个Jenkins构建中的一些代码,它使用递归来获取Jenkins的下游作业的URLPython递归树示例,python,recursion,Python,Recursion,我正在分析一个Jenkins构建中的一些代码,它使用递归来获取Jenkins的下游作业的URL def get_all_downstream_jobs_urls(ds_jobs: set = None): global JENKINS_JOBS if not ds_jobs: ds_jobs = set(); ds_jobs.update(extract_ds_job_url(get_ds_jobs(BASE_JOB_URL))) temp = d
def get_all_downstream_jobs_urls(ds_jobs: set = None):
global JENKINS_JOBS
if not ds_jobs:
ds_jobs = set(); ds_jobs.update(extract_ds_job_url(get_ds_jobs(BASE_JOB_URL)))
temp = ds_jobs
for _ in ds_jobs.copy():
result = extract_ds_job_url(get_ds_jobs(_)) # <--- jenkins rest api call
if result: temp.update(result); JENKINS_JOBS.update(temp);
else: return temp
return get_all_downstream_jobs_urls(temp)
def get_all_down_jobs_url(ds_jobs:set=None):
全球JENKINS_就业
如果不是ds_作业:
ds_jobs=set();更新(提取任务url(获取任务(基本任务url)))
temp=ds\u作业
对于ds_作业中的u.copy():
result=extract_ds_job_url(get_ds_jobs(_))#如果extract_ds_job_url(get_ds_jobs(BASE_job_url))
返回一个空集,则永远调用get_all down_jobs_url(temp)
。这是因为for
循环不会做任何事情
顶部的测试应检查是否有None
:
if ds_jobs is None:
对于ds\u作业
为空的单独测试应结束递归:
if not ds_jobs:
# no downstream jobs to process
return set()
我不能保证其余的逻辑,但代码中肯定有很多样式错误。我将对其进行重构,以至少消除其中一些错误:
JENKINS_作业
永远不会反弹,因此global JENKINS_作业
是冗余和混乱的,应该删除
- 不清楚函数为什么要更新全局值并返回结果集。它应该做一个或另一个,而不是两个都做
是一个一次性变量。它表示将不使用该值。但在这里,代码确实使用了它。它应该改名为job\u url
- 你真的不应该使用
代码>在生产代码中。将代码放在单独的行中
ds\u jobs=set()
temp
不是一个好的变量名,updated
可能是一个更好的名称。分配时应将其复制,以便updated=set(ds_作业)
,并且可以从for
循环中删除.copy()
调用
- 当第一个作业URL没有下游URL时,返回的
可能也不是您想要的
- 如果你真的想要一个下游URL的树,递归调用不应该试图传递到目前为止收集的所有作业URL!对于已经检查过的作业URL,很可能会一次又一次地调用jenkins API
以下代码通过使用堆栈来删除递归,并保证只为每个作业URL调用Jenkins API一次:
最后但并非最不重要的一点是,我强烈怀疑使用第三方库(如)会使这一切变得更加简单;Jenkins API可能只允许您在一次调用中查询此信息,但库可能会为您执行此类调用,并为您提供易于解析的Python对象以获取信息。我在这里看不到任何递归,除非extract\u ds\u job\u url()
或get\u jobs()
进行递归调用。这里缺少的东西太多,根本无法提供帮助;ds_jobs.update(…)
应该是ds_jobs=set(…)
。global JENKINS\u JOBS
行是多余的(函数中没有任何名称重新绑定)。不要对变量名使用。
如果您实际使用了该值,。
表示您打算忽略该值。如果是URL,请将变量命名为URL
temp
也不是一个好名字,你应该使用temp=ds_jobs.copy()
而不是为循环创建副本。udpated,代码。@MartijnPieters,这不是我的代码。请记住这一点—很好的解释和备选代码示例。谢谢
def get_all_downstream_jobs_urls():
ds_jobs = set()
stack = [extract_ds_job_url(get_ds_jobs(BASE_JOB_URL))]
while stack:
job_url = stack.pop()
if job_url in ds_jobs:
# already seen before, skip
continue
ds_jobs.add(job_url)
# add downstream jobs to the stack for further processing
stack.extend(extract_ds_job_url(get_ds_jobs(job_url)))
return ds_jobs