如何 运行 带有布尔参数的 Python 文件

How to run a Python file with boolean arguments

我有一个 .py 文件,其功能基本上是将 .csv 文件转换为 .pkl 文件。当从终端调用时,该文件应该根据输入是否为真在英制和公制之间转换测量值。例如

python3 file.py imperial_units=Truepython3 file.py imperial_units=False 如果没有像 python3 file.py 这样的参数提供,英制单位应该默认为 True:

这是我的尝试:

import json, sys
import pandas as pd

def log_to_pickle(units):
    ...
            
            if units == True: # If units == True, convert all metric to imperial
                print('Imperial True')
                if imperial_unit == False:
                    ...

            elif units == False: # If units == False, convert all imperial to metric
                print('Imperial False')
                if imperial_unit == True:
                    ...

            ...

if __name__ == "__main__":
    if sys.argv == True or sys.argv == '':
        log_to_pickle(True)
    else:
        log_to_pickle(False)

我在 if/elif 块中添加了打印语句,以查看我的输入是否有效。我 运行 python3 file.py imperial_units=True 并且输出是 'Imperial False'

我做错了什么?

对于这种类型的东西,我会使用 argparse。使用布尔标志参数。我也想提供一个正面和负面的版本以便于使用。

import argparse

...

if __name__ == "__main__":
    parser = argparse.ArgumentParser(prog='log-to-pickle')

    parser.add_argument('--imperial-units', dest='imperial_units', action='store_true')
    parser.add_argument('--no-imperial-units', dest='imperial_units', action='store_false')
    parser.set_defaults(imperial_units=True)

    args = parser.parse_args()

    log_to_pickle(args.imperial_units)

使用 argparse 你也会得到一些很好的帮助信息:

$ python3 file.py -h
usage: log-to-pickle [-h] [--imperial-units] [--no-imperial-units]

optional arguments:
  -h, --help           show this help message and exit
  --imperial-units
  --no-imperial-units

现在您可以像这样调用应用程序:

# These are the same given the default.
$ python3 file.py
$ python3 file.py --imperial-units

或做负片:

$ python3 file.py --no-imperial-units

如果你真的想为 bool 标志提供一个字符串参数,那么我会创建一个自定义方法来将字符串转换为布尔值:

import argparse


def bool_arg(val):
    return val.lower() in ('y', 'yes', 't', 'true', 'on', '1')


if __name__ == "__main__":
    parser = argparse.ArgumentParser(prog='log-to-pickle')

    parser.add_argument('--imperial-units', type=bool_arg, default=True)

    args = parser.parse_args()

    print(args.imperial_units)

示例:

$ python3 file.py --imperial-units y
True

$ python3 file.py --imperial-units True
True

$ python3 file.py --imperial-units 0
False

这里有一些错误,但根本原因是代码没有正确使用 sys.argv。尝试打印 sys.argv:

if __name__ == "__main__":
    import sys
    print(sys.argv)
$ python3 argv.py imperial_units=True
['argv.py', 'imperial_units=True']

您需要解析命令行参数。

if __name__ == "__main__":
    if len(sys.argv) <= 1 or sys.argv[1] == "imperial_units=True":
        log_to_pickle(True)
    else:
        log_to_pickle(False)

查看 argparse 包以获得更强大的命令行参数处理。

sys.argv 提供参数列表。您可以遍历它以找到包含“imperial_units”的参数。然后您可以处理它以获得布尔值。

if __name__ == "__main__":
    #Find arguments which contain imperial_units
    arg = [x.split("=")[1] for x in sys.argv if "imperial_units" in x]
    #If the length is 0, no args were found, default to true
    #Otherwise use value after = and convert it to bool
    arg = True if len(arg) == 0 else bool(arg[0])
    log_to_pickle(arg)

argparse 生成一个带有帮助文本的更加用户友好的程序,并使用可以说是更标准的破折号分隔参数方法。由于您只想要一件事,即度量单位,我认为最好使用包含默认值的选择标志来实现,但您可以使用默认为 False 的单个参数,例如 --use-metric

#!/usr/bin/env python3
import argparse

parser = argparse.ArgumentParser(description='CSV to Pickle with unit conversion to metric')
parser.add_argument('-u', '--unit', default='imperial', choices=['imperial', 'metric'],
                    help='Source unit type (imperial or metric)')
parser.add_argument('from_file', help="CSV file to convert")
parser.add_argument('to_file', help="Converted Pickle file")

args = parser.parse_args()
print(args.unit)

使用该程序的选项是

$ ./test.py --help
usage: test.py [-h] [-u {imperial,metric}] from_file to_file

CSV to Pickle with unit conversion to metric

positional arguments:
  from_file             CSV file to convert
  to_file               Converted Pickle file

optional arguments:
  -h, --help            show this help message and exit
  -u {imperial,metric}, --unit {imperial,metric}
                        Source unit type (imperial or metric)

$ ./test.py --unit metric aaa.csv aaa.pkl
metric
$ ./test.py -u imperial aaa.csv aaa.plk
imperial
$ ./test.py aaa.csv aaa.pkl
imperial
$ ./test.py --unit=other aaa.csv aaa.pkl
usage: test.py [-h] [-u {imperial,metric}] from_file to_file
test.py: error: argument -u/--unit: invalid choice: 'other' (choose from 'imperial', 'metric')