如何从用户那里获取文件路径并将其传递给函数(argparse)

3

我正在编写一个程序,对文件内容执行不同的功能。目前文件存储在变量中,然后作为参数传递给每个函数:

file = "path/to/file"

我希望做的是允许用户使用我已设置好的命令行函数输入路径,并将其传递给我的函数。然而,我不确定如何将其实现到这里的命令行文件中。
cli.py
import os, argparse
from . import parse


def validate_file(filename):
    if not os.path.exists(filename):
        raise argparse.ArgumentTypeError("{0} does not exist".format(filename))
    return filename


def dump(filename):
    for record in parse.uniprot_records(filename):
        print(record)

...
(more function definitions)
...

def cli():
    # Create a new parser
    parser = argparse.ArgumentParser(description="UniProt Analysis")

    # Input file
    parser.add_argument("-i", "--input", dest="filename", type=validate_file, required=True, help="enter input file", metavar="FILE")

    subparsers = parser.add_subparsers(help="Enter one of the arguments to run function")

    # Add subparsers
    subparsers.add_parser("dump", help="prints all records").set_defaults(func=dump)

    # Parse the command line
    args = parser.parse_args()
    print(type(args.filename))

    # Take the func argument, which points to our function and call it
    args.func(args)

我希望能够通过命令行传递文件,并执行想要的功能,例如: pipenv run python program.py path/to/file dump 编辑:已向解析器添加参数以获取用户的输入文件。该文件随后被传递到dump函数中,并由此函数传递给以下函数: parse.py
import gzip
from Bio import SeqIO


def uniprot_records(f):
    records = []

    handle = gzip.open(f)
    for record in SeqIO.parse(handle, "uniprot-xml"):
        records.append(record)
    return records

我的主函数在一个单独的模块中,它只是调用了cli函数。当我尝试运行pipenv run python uniplot.py -i path/to/file dump时,它会给出以下错误:

文件 "/Users/john/workspace/practical-2/uniplot/parse.py",第 24 行,函数 uniprot_records handle = gzip.open(file_location)

文件 "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/gzip.py",第 57 行,函数 open raise TypeError("filename must be a str or bytes object, or a file")

类型错误:文件名必须是字符串或字节对象,或者是文件。

dump 应该在使用 gzip 解压后打印出给定文件的全部内容。


是的,那听起来有些道理。我会尝试实现它。 - Johnboy
好的,关于将文件传递给函数似乎已经可以工作了。但是现在我收到了一个 TypeError 错误:文件名必须是 str 或 bytes 对象,或者是文件...处理文件的方法正在使用 gzip 解压缩文件,我认为通过命令行传递文件应该是 str 类型的... - Johnboy
你遇到了什么错误?你是如何传递 filename 的? - PyPingu
已更新原始代码。我也进行了测试,它显示为字符串... 令人困惑。 - Johnboy
哎呀,现在它可以工作了。但是我不能在文件参数的类型属性中使用 validate_file(filename),因为它需要一个参数。此时我无法传递任何东西。顺便说一下,谢谢你! - Johnboy
显示剩余7条评论
3个回答

4
请使用下面的语法。
import argparse, os
from argparse import ArgumentParser


def validate_file(f):
    if not os.path.exists(f):
        # Argparse uses the ArgumentTypeError to give a rejection message like:
        # error: argument input: x does not exist
        raise argparse.ArgumentTypeError("{0} does not exist".format(f))
    return f


if __name__ == "__main__":

    parser = ArgumentParser(description="Read file form Command line.")
    parser.add_argument("-i", "--input", dest="filename", required=True, type=validate_file,
                        help="input file", metavar="FILE")
    args = parser.parse_args()
    print(args.filename)

1
你可以使用 parser.add_argument 添加参数到 parser 中。这些参数将被作为一个 Namespace 对象传递给调用的函数:
import argparse

def dump(args):
    print(args.path)


def cli():
    # Create a new parser
    parser = argparse.ArgumentParser()

    subparsers = parser.add_subparsers()

    parser.add_argument("path")

    # Add subparsers
    subparsers.add_parser("dump").set_defaults(func=dump)

    # Parse the command line
    args = parser.parse_args()

    # Take the func argument, which points to the function and call it
    args.func(args)

cli()

命令看起来像这样:

python cli.py dump some/file

至于推荐的做法,这将取决于您的用例。通过命令行传递所有参数到脚本中将使您能够更轻松地以某种自动化方式运行脚本,而不是通过交互式输入。它还将允许您更轻松地在终端中重新运行相同的任务。如果这对您不相关,则这主要是个人喜好问题。


0
对于任何需要用户输入的文件,我通常会创建一个解析器函数。 我会按照以下方式进行:
#! /usr/bin/env python

import argparse
import sys

def my_parser():
    """
    Creates argument parser.
    """

    parser = argparse.ArgumentParser()

    # Input File
    parser.add_argument('path',
                        type=str,
                        help='some help text')

    # function name
    parser.add_argument('function',
                        type=str,
                        help='some help text')

    return parser


def main(args=None):
    """
    display user input
    """

    # Create parser
    subparser = my_parser()

    # Parse command-line input
    args = subparser.parse_args(sys.argv[1:])
    print('User path is -> {}'.format(args.path))
    print('User function is -> {}'.format(args.function))


if __name__ == "__main__":
    main()

1) 你可以从用户那里获取路径 2) 他想要执行的函数名称

从命令行中,你可以这样运行它:

python pathtoyourpythonscript filepath functionname

然后在主函数内,您可以根据用户输入编写if else循环。希望这能帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接