【问题标题】:Arg parse: parse file name as string (python)argparse:将文件名解析为字符串(python)
【发布时间】:2017-01-13 22:47:18
【问题描述】:

我想将文件名作为字符串解析到我的脚本中,而不是直接将文件转换为对象。

这是一个示例代码,test.py

import argparse
import os.path
def is_valid_file(parser, arg):
      if not os.path.exists(arg):
           parser.error("The file %s does not exist! Use the --help flag for input options." % arg)
      else:
           return open(arg, 'r')

parser = argparse.ArgumentParser(description='test') 
parser.add_argument("-test", dest="testfile", required=True,
                    help="test", type=lambda x: is_valid_file(parser, x))
args = parser.parse_args()    
print args.testfile

testfile 是一个.txt 文件,其中包含:1,2,3,4

原则上希望print args.testfile 将调用的testfile 名称作为字符串返回:

$ python test.py -test test.txt
>> "test.txt"

为了实现这一点,我需要阻止 argparser 将 test.txt 转换为对象。我该怎么做?

非常感谢!

【问题讨论】:

  • 你试过parser.add_argument("-test", dest="testfile", required=True, help="test")
  • 感谢 Jean-François,我之前编写了一个函数来检查文件是否存在,从代码中删除它可以解决问题。
  • 上述函数:#_____ def is_valid_file(parser, arg): if not os.path.exists(arg): parser.error("文件%s不存在!使用--输入选项的帮助标志。” % arg) else: return open(arg, 'r') #_______

标签: python string filenames argparse


【解决方案1】:

您可以如下修改您的函数以在检查字符串是否存在后返回:

def is_valid_file(parser, arg):
      if not os.path.exists(arg):
           parser.error("The file %s does not exist! Use the --help flag for input options." % arg)
      else:
           return arg

还有一种更直接的方法:

parser.add_argument("-test", dest="testfile", required=True,
                    help="test", type=file)  # file exists in python 2.x only

parser.add_argument("-test", dest="testfile", required=True,
                    help="test", type=lambda f: open(f))  # python 3.x

args = parser.parse_args()    
print(args.testfile.name)  # name of the file from the file handle

实际上args.testfile 是文件句柄,由 argparser 打开(如果找不到则异常)。您可以直接从中读取。

【讨论】:

    【解决方案2】:

    FileType 类型工厂完成了您的代码所做的大部分工作,但消息机制略有不同:

    In [16]: parser=argparse.ArgumentParser()
    In [17]: parser.add_argument('-f',type=argparse.FileType('r'))
    
    In [18]: args=parser.parse_args(['-f','test.txt'])
    In [19]: args
    Out[19]: Namespace(f=<_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>)
    In [20]: args.f.read()
    Out[20]: '  0.000000,  3.333333,  6.666667, 10.000000, 13.333333, 16.666667, 20.000000, 23.333333, 26.666667, 30.000000\n'
    In [21]: args.f.close()
    

    对于有效名称,它会打开文件,您可以使用和关闭该文件。但是你不能在 with 上下文中使用它。

    如果文件不存在,则退出并显示使用情况和cant open 消息。

    In [22]: args=parser.parse_args(['-f','test11.txt'])
    usage: ipython3 [-h] [-f F]
    ipython3: error: argument -f: can't open 'test11.txt': [Errno 2] No such file or directory: 'test11.txt'
    

    FileType __call__ 使用argparse.ArgumentTypeError 处理错误

       except OSError as e:
            message = _("can't open '%s': %s")
            raise ArgumentTypeError(message % (string, e))
    

    使用这种错误机制,并省略你的open 我建议:

    def valid_file(astring):
        if not os.path.exists(astring):
            msg = "The file %s does not exist! Use the --help flag for input options." % astring
            raise argparse.ArgumentTypeError(msg)
        else:
            return astring
    

    可以用作:

    In [32]: parser=argparse.ArgumentParser()
    In [33]: parser.add_argument('-f',type=valid_file)
    
    In [34]: args=parser.parse_args(['-f','test11.txt'])
    usage: ipython3 [-h] [-f F]
    ipython3: error: argument -f: The file test11.txt does not exist! Use the --help flag for input options.
    An exception has occurred, use %tb to see the full traceback.
    
    SystemExit: 2
    
    In [35]: args=parser.parse_args(['-f','test.txt'])
    In [36]: args
    Out[36]: Namespace(f='test.txt')
    In [37]: with open(args.f) as f:print(f.read())
      0.000000,  3.333333,  6.666667, 10.000000, 13.333333, 16.666667, 20.000000, 23.333333, 26.666667, 30.000000
    

    http://bugs.python.org/issue13824 担心FileType 打开文件但不关闭它。我提出了一个FileContext,仿照FileType,但不是打开文件,而是返回一个可以用作的对象:

    with arg.file() as f:
        f.read()
    

    它将执行文件存在性或可创建性测试,而无需实际打开或创建文件。这是一个更复杂的解决方案。

    【讨论】:

      猜你喜欢
      • 2017-08-31
      • 2021-07-25
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-22
      • 2015-02-16
      相关资源
      最近更新 更多