【问题标题】:How to pass a function, list, among others as args to argparse in Python?如何在 Python 中将函数、列表等作为 args 传递给 argparse?
【发布时间】:2020-08-09 06:48:45
【问题描述】:

我有以下有效的脚本,我试图避免在同一个模块中使用'__main__'

def download():
    urls = \
        [
            'https://ipleak.net/json',
            'https://httpbin.org/get'
        ] * 4

    downloads = asyn.init_download(urls, "json")
    return downloads

def pprint_json(d):
    print(json.dumps(d, indent=4, sort_keys=True))

def multiprocess_list(n_pools, func, list):
    executor = concurrent.futures.ProcessPoolExecutor(n_pools)
    futures = [executor.submit(func, item) for item in list]
    concurrent.futures.wait(futures)

if __name__ == '__main__':
    multiprocess_list(4, pprint_json, download())

download() 函数,顾名思义,使用asyncioaiohttp 异步下载urls

我想从任何地方“全局”执行multiprocess_list

def multiprocess_list(n_pools, func, list):
    executor = concurrent.futures.ProcessPoolExecutor(n_pools)
    futures = [executor.submit(func, item) for item in list]
    concurrent.futures.wait(futures)

def main(args):
    parser = argparse.ArgumentParser(description="Multiprocessing a list.")
    parser.add_argument("-n", "--n_pools", type=int, required=True)
    parser.add_argument("-f", "--function", required=True)
    parser.add_argument("-l", "--list", required=True)
    args = parser.parse_args(args)

    multiprocess_list(args.n_pools, args.function, args.list)

if __name__ == '__main__':
    import sys
    main(sys.argv[1:])

将上面的 module 导入到任何其他 python 文件中,并可能像这样运行它:(虽然不起作用)

def download():
    urls = \
        [
            'https://ipleak.net/json',
            'https://httpbin.org/get'
        ] * 4

    downloads = asyn.init_download(urls, "json")
    return downloads

def pprint_json(d):
    print(json.dumps(d, indent=4, sort_keys=True))

mp.main(["-n", 4, "-f", pprint_json, "-l", download()])

这给了我一个错误:

if not arg_string[0] in self.prefix_chars: TypeError: 'int' object is not subscriptable

因此,将一个参数作为要运行的函数传递,将另一个参数作为列表或返回类似download() 的列表的函数传递。

  • 这可以在 python 中完成吗?
  • 如果是,有人可以解释一下吗?
  • 我的方法是正确的还是完全失去了它?

注意:我的解释器使用 Python3.8,我对 python 有点陌生,请多多包涵。

【问题讨论】:

  • “虽然不起作用”?你得到什么错误?

标签: python multithreading module arguments argparse


【解决方案1】:

Argparse 需要一个字符串列表,并且可能会阻塞其他类型。如果您引用4,它是否有效?

mp.main(["-n", "4", "-f", pprint_json, "-l", download()])

pprint_jsondownload() 的结果也应该是字符串才能正常工作。

这种创建替代 argv 的方法并不总是很疯狂,但在您的情况下,如果您已经拥有 args,为什么还要调用 main() 为您解析 args?为什么不用适当的参数直接调用multiprocess_list()

之所以使用main(),是因为我以后可能会在multiprocess_list()之外添加更多功能

然后,您可以在从 Python 调用脚本时直接调用它们,而不是创建另一个参数来选择其中一个。您仍然可以使用 main() 从命令行解析 args。

下一个错误TypeError: 'function' object is not subscriptable

啊,那也不是字符串。在那种情况下,我也不希望它在命令行中工作。你做了那么多工作了吗?

你可以试试

mp.main(["-n", "4", "-f", "pprint_json", "-l", download()])

但是main() 必须能够以某种方式将该函数名解释为函数。也许像

multiprocess_list(args.n_pools, getattr(foo, args.function), args.list)

其中foo 是您保留可选功能的模块。

【讨论】:

  • 感谢您的回答@gilch,我收到下一个错误TypeError: 'function' object is not subscriptable。使用main()的原因是因为我以后可能会添加更多的功能,除了multiprocess_list()可能使用parser.add_argument("function", nargs="?", choices=['multiprocess_list', 'function2', 'function2'], default='multiprocess_list', )
  • @gilch:如果我错了,请纠正我:这不会导致循环导入吗?对你们中的任何一个的问题:可以使用 subprocess 调用 multiprocess_list 文件而不是导入它吗?
  • 您实际上有一点@mechanical_meat 我可能以错误的方式接近这个问题。 subprocess 是我正在寻找的东西,但我不确定如何实现它。 pprint_json() 只是一个例子,最终我正在寻找 json_normalize() 或同时将所有接收到的数据中的 html 解析到一个数据帧中。
  • @mechanical_meat foo 本来是一个由主模块导入的单独模块,所以不,不是循环的。如果你想避免一个单独的模块,你可以把可选择的函数放在一个字典中。
猜你喜欢
  • 2020-05-11
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 2012-03-12
  • 1970-01-01
  • 2016-04-28
  • 2019-09-09
相关资源
最近更新 更多