简体   繁体   English

Arg解析:将文件名解析为字符串(python)

[英]Arg parse: parse file name as string (python)

I would like to parse the name of a file into my script as a string, rather than directly converting the file into an object. 我想将文件名解析为字符串形式的脚本,而不是直接将文件转换为对象。

Here is a sample code, test.py : 这是一个示例代码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 is a .txt file containing: 1,2,3,4 testfile是一个.txt文件,其中包含: 1,2,3,4

In principal would like print args.testfile to return the invoked name of testfile as a string: 原则上,希望print args.testfile以字符串形式返回testfile的调用名称:

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

To achieve this I need to prevent argparser from converting test.txt into an object. 为此,我需要防止argparser将test.txt转换为对象。 How can I do this? 我怎样才能做到这一点?

Many thanks! 非常感谢!

you can modify your function as follows to return the string after having checked it exists: 您可以按如下所示修改函数,以在检查字符串存在后返回该字符串:

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

There's also a more direct method: 还有一种更直接的方法:

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

actually args.testfile is the file handle, opened by argparser (exception if not found). 实际上args.testfile是由argparser打开的文件句柄(如果找不到,则为例外)。 You can read from it directly. 您可以直接阅读。

The FileType type factory does most of what your code does, with a slightly different message mechanism: 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()

For a valid name it opens the file, which you can use and close. 对于有效名称,它将打开文件,您可以使用它并关闭它。 But you can't use it in a with context. 但是您不能在with上下文中使用它。

If the file doesn't exist it exits with usage and a cant open message. 如果该文件不存在,它将退出并显示使用情况和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__ handles the error with an argparse.ArgumentTypeError FileType __call__使用argparse.ArgumentTypeError处理错误

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

Using this error mechanism, and omitting your open I'd suggest: 使用此错误机制,并省略您的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

Which could be used as: 可以用作:

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 worries about FileType opening a file but not closing it. http://bugs.python.org/issue13824担心FileType打开文件而不关闭文件。 I proposed a FileContext , modeled on FileType , but instead of opening the file, returns an object that can be use as: 我提出了一个以FileType为模型的FileContext ,但是没有打开文件,而是返回了一个可用作以下对象的对象:

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

It would do the file existence or creatablity testing, without actually opening or creating the file. 它将执行文件存在性或可创建性测试,而无需实际打开或创建文件。 It's a more complicated solution. 这是一个更复杂的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM