如何在Python父脚本中调用带argparse的子脚本并获取结果?
问题描述
我希望在parent.py中获取child.py里的my_splited_text(类型为list),当前通过JSON序列化/反序列化的方式实现,但想知道有没有更简便、更优的方案。
现有代码
child.py
import argparse import json parser = argparse.ArgumentParser(description='A sample script with argparse') parser.add_argument('--query', type=str, help='Query Phrase', default="I love coding!") args = parser.parse_args() def customized_fcn(inp="This is my sample text!"): result=inp.split() return result def main(): my_splited_text=customized_fcn(inp=args.query) # Serialize the list into a string and print it serialized_result = json.dumps(my_splited_text) print('Serialized Result:', serialized_result) if __name__ == '__main__': main()
parent.py
import subprocess import json import re def run_my_script(): command = ['python', 'child.py', '--query', 'I want to eat an ice-cream right now!'] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) return_code = process.wait() stdout, stderr = process.communicate() # Extract and deserialize the result serialized_result = re.search(r'Serialized Result: (.+)', stdout).group(1) my_splited_text=json.loads(serialized_result) print('Captured Result:', type(my_splited_text), my_splited_text) run_my_script()
更优实现方案
下面几种方法比当前的JSON序列化/反序列化更简便高效:
1. 直接导入模块调用函数(最简便)
如果两个脚本在同一目录下,完全不需要用subprocess启动独立进程,直接在parent.py中导入child.py的函数,直接调用获取结果:
修改后的parent.py:
import child def run_my_script(): # 直接调用child中的函数,传入参数 my_splited_text = child.customized_fcn(inp='I want to eat an ice-cream right now!') print('Captured Result:', type(my_splited_text), my_splited_text) run_my_script()
如果需要保留child.py的命令行参数逻辑,可以在parent.py中模拟参数解析:
import child import sys def run_my_script(): # 模拟命令行参数 sys.argv = ['child.py', '--query', 'I want to eat an ice-cream right now!'] # 重新解析参数 child.args = child.parser.parse_args() # 调用函数获取结果 my_splited_text = child.customized_fcn(inp=child.args.query) print('Captured Result:', type(my_splited_text), my_splited_text) run_my_script()
这种方式省去了进程间通信和序列化的开销,是效率最高的方案。
2. 让child.py输出纯JSON(简化解析)
如果必须用独立进程(比如child.py需要环境隔离、有特殊依赖等),可以简化child.py的输出,直接打印序列化后的JSON字符串,去掉多余前缀,这样parent.py无需正则提取,直接读取stdout反序列化:
修改child.py的main函数:
def main(): my_splited_text=customized_fcn(inp=args.query) # 直接输出纯JSON字符串 print(json.dumps(my_splited_text))
修改后的parent.py:
import subprocess import json def run_my_script(): command = ['python', 'child.py', '--query', 'I want to eat an ice-cream right now!'] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = process.communicate() # 直接反序列化stdout内容 my_splited_text = json.loads(stdout.strip()) print('Captured Result:', type(my_splited_text), my_splited_text) run_my_script()
这种方式去掉了正则匹配步骤,代码更简洁可靠,避免了正则匹配失败的风险。
3. 使用multiprocessing模块(进程间共享数据)
如果需要严格的进程隔离,还可以用multiprocessing模块实现进程间通信,通过队列传递结果:
修改child.py,封装可被多进程调用的逻辑:
import argparse def customized_fcn(inp="This is my sample text!"): result=inp.split() return result def worker(query, queue): result = customized_fcn(inp=query) queue.put(result) if __name__ == '__main__': parser = argparse.ArgumentParser(description='A sample script with argparse') parser.add_argument('--query', type=str, help='Query Phrase', default="I love coding!") args = parser.parse_args() print(customized_fcn(inp=args.query))
修改后的parent.py:
import multiprocessing import child def run_my_script(): query = 'I want to eat an ice-cream right now!' # 创建队列用于传递结果 queue = multiprocessing.Queue() # 创建子进程 p = multiprocessing.Process(target=child.worker, args=(query, queue)) p.start() p.join() # 从队列获取结果 my_splited_text = queue.get() print('Captured Result:', type(my_splited_text), my_splited_text) run_my_script()
这种方式适合需要独立进程环境的场景,比subprocess更灵活,无需字符串序列化。
内容的提问来源于stack exchange,提问作者farid
相关产品推荐
相关产品推荐

