如何使用 argparse 中的位置参数。Namespace

how to use positional argument from argparse.Namespace

提问人:novski 提问时间:2/7/2023 更新时间:2/8/2023 访问量:116

问:

我正在尝试在两个文件中构建一个 cli 和 wxpython gui 应用程序。 wx 应用调用 cli 应用以获取功能。 当我将 wx 应用程序中的参数包装到命名空间时,cli 应用程序不会接受它。window.py: error: the following arguments are required: filepath

我简化了文件以仅显示相关部分:

window.py

import os
from argparse import Namespace
from threading import Thread
from main import main

def window():
    try:
        print('window try')
        args = Namespace(
                        filepath = os.getcwd()+'file.xy',
                        outputpath =  os.getcwd()
                        )
        thread = Thread(target=main, args=(args,))
        thread.start()
        thread.join()
    except Exception as e:
        print(f'error:{e}')

if __name__ == '__main__':
     window()

main.py

import os
import argparse


def main(*args):
    print(f'START main args:{args}, type of args:{type(args)}')
    if args:
        args=args[0]
    print(f'tuple0:{args}, type of args:{type(args)}')
    parser = argparse.ArgumentParser()
    parser.add_argument('filepath', default=os.getcwd())
    parser.add_argument('-o', dest='outputpath')
    args = parser.parse_args()
    print(f'DONE main args:{args}, type of args:{type(args)}')

if __name__ == '__main__':
    main()

输出:

➜  argparse python3 main.py ~/Documents/
START main args:(), type of args:<class 'tuple'>
tuple0:(), type of args:<class 'tuple'>
DONE main args:Namespace(filepath='/Users/novski/Documents/', outputpath=None), type of args:<class 'argparse.Namespace'>
➜  argparse python3 window.py      
window try
START main args:(Namespace(filepath='/Users/novski/Documents/argparse/file.xy', outputpath='/Users/novski/Documents/argparse'),), type of args:<class 'tuple'>
tuple0:Namespace(filepath='/Users/novski/Documents/argparse/file.xy', outputpath='/Users/novski/Documents/argparse'), type of args:<class 'argparse.Namespace'>
usage: window.py [-h] [-o OUTPUTPATH] filepath
window.py: error: the following arguments are required: filepath

为什么当我把它从我的 window.py 交给 main.py 时没有被接受?Namespace(filepath...filepathargs

有没有更好的解决方案,如何从 GUI (window.py) 使用我的 cli 应用程序 (main.py)?

Python 命名空间 python-multithreading argparse

评论

0赞 hpaulj 2/8/2023
parser.parse_args()解析。事实上,你已经有一个变量被调用,但并不会改变这种行为。sys.argvargs

答:

1赞 hpaulj 2/8/2023 #1

有条件地运行解析器怎么样?

if args:
    args=args[0]
    print(f'tuple0:{args}, type of args:{type(args)}')
else:
    parser = argparse.ArgumentParser()
    parser.add_argument('filepath', default=os.getcwd())
    parser.add_argument('-o', dest='outputpath')
    args = parser.parse_args()
0赞 chepner 2/8/2023 #2

您需要传递希望解析器解析的字符串列表,而不是它最终可能返回的对象。

def window():
    try:
        print('window try')
        args = ['-o', os.getcwd(), os.getcwd() + 'file.xy']
        thread = Thread(target=main, args=(args,))
        thread.start()
        thread.join()
    except Exception as e:
        print(f'error:{e}')

# Parse args will parse whatever list main() receives, or sys.argv[1:]
# if nothing is given to main().
def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('filepath', default=os.getcwd())
    parser.add_argument('-o', dest='outputpath')
    args = parser.parse_args(args)
    print(f'DONE main args:{args}, type of args:{type(args)}')
0赞 CristiFati 2/8/2023 #3

列出 [Python.Docs]: argparse - 命令行选项、参数和子命令的解析器

我修复了您代码中的错误:

  • main 接收到的参数传递给 parse_args(而不是依赖于 sys.argv)

  • 删除(不知道它是干什么用的,而且它很丑(看起来像是解决错误))if args: args = args[0]

  • 放弃命名空间(因为默认的命名空间绰绰有余)

  • 将参数作为序列传递给 main(在(上面的)URL 中多次举例)

  • 此外,将解析选项更改为(我认为是)用户友好的表单

演示:

  • main.py

    #!/usr/bin/env python
    
    import argparse
    import os
    import sys
    
    
    def main(*argv):
        print(f"Start main: {argv}")
        parser = argparse.ArgumentParser()
        parser.add_argument("--filepath", "-f", default=os.getcwd())
        parser.add_argument("--outputpath", "-o",)
        parsed_args = parser.parse_args(args=argv)
        print(f"Parsed arguments: {parsed_args}")
    
    
    if __name__ == "__main__":
        print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                       64 if sys.maxsize > 0x100000000 else 32, sys.platform))
        rc = main(*sys.argv[1:])
        print("\nDone.\n")
        sys.exit(rc)
    
  • window.py

    #!/usr/bin/env python
    
    import os
    import sys
    from threading import Thread
    
    from main import main
    
    
    def window():
        try:
            print("Start wwindow")
            args = ("-f", os.path.join(os.getcwd(), "file.py"), "-o", os.getcwd())
            thread = Thread(target=main, args=args)
            thread.start()
            thread.join()
        except Exception as e:
            print(f"Exception: {e}")
    
    
    if __name__ == "__main__":
        print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                       64 if sys.maxsize > 0x100000000 else 32, sys.platform))
        rc = window()
        print("\nDone.\n")
        sys.exit(rc)
    

输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q075373104]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./main.py
Python 3.10.9 (tags/v3.10.9:1dd9be6, Dec  6 2022, 20:01:21) [MSC v.1934 64 bit (AMD64)] 064bit on win32

Start main: ()
Parsed arguments: Namespace(filepath='e:\\Work\\Dev\\StackOverflow\\q075373104', outputpath=None)

Done.


[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./main.py -f file
Python 3.10.9 (tags/v3.10.9:1dd9be6, Dec  6 2022, 20:01:21) [MSC v.1934 64 bit (AMD64)] 064bit on win32

Start main: ('-f', 'file')
Parsed arguments: Namespace(filepath='file', outputpath=None)

Done.


[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./main.py -f file -o dir
Python 3.10.9 (tags/v3.10.9:1dd9be6, Dec  6 2022, 20:01:21) [MSC v.1934 64 bit (AMD64)] 064bit on win32

Start main: ('-f', 'file', '-o', 'dir')
Parsed arguments: Namespace(filepath='file', outputpath='dir')

Done.


[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.10_test0\Scripts\python.exe" ./window.py
Python 3.10.9 (tags/v3.10.9:1dd9be6, Dec  6 2022, 20:01:21) [MSC v.1934 64 bit (AMD64)] 064bit on win32

Start wwindow
Start main: ('-f', 'e:\\Work\\Dev\\StackOverflow\\q075373104\\file.py', '-o', 'e:\\Work\\Dev\\StackOverflow\\q075373104')
Parsed arguments: Namespace(filepath='e:\\Work\\Dev\\StackOverflow\\q075373104\\file.py', outputpath='e:\\Work\\Dev\\StackOverflow\\q075373104')

Done.