新增Click命令行选项--realtime/--interval后无法使用的问题求助
问题原因与修复方案
问题根源
你用@click.group()装饰了主函数cli,但click.group的作用是创建命令组,用来管理多个子命令。它身上定义的所有选项,都是给下属的子命令使用的,而非直接供cli自身执行。当你直接运行脚本时,Click会把cli视为一个命令组,而非可执行命令,因此你新增的--realtime、--interval等选项虽然会在--help中展示,但实际执行时无法被识别——因为命令组本身不处理这些参数,需要子命令来接收。
修复方案
根据你的需求,有两种修复方式:
方式一:不需要子命令时(直接运行主函数)
把@click.group()替换为@click.command(),这样cli会被当成独立可执行的命令,所有选项都能被正确解析:
from typing import Optional, List, Set, Dict import click import pandas as pd class Config(object): def __init__(self): self.cv_data: Optional[List[pd.DataFrame]] = None self.cv_labels: Optional[pd.DataFrame] = None self.train_data: Optional[List[pd.DataFrame]] = None self.train_labels: Optional[pd.DataFrame] = None self.test_data: Optional[List[pd.DataFrame]] = None self.test_labels: Optional[pd.DataFrame] = None self.classes: Optional[Set[int]] = None self.num_classes: Optional[int] = None self.ts_length: Optional[int] = None self.variate: Optional[int] = None self.strategy: Optional[str] = None self.timestamps: Optional[List[int]] = None self.folds: Optional[int] = None self.target_class: Optional[int] = None self.output: Optional[click.File] = None self.java: Optional[bool] = None self.file: Optional[click.File] = None self.splits: Optional[dict] = None self.make_cv: Optional[bool] = None self.realtime: Optional[bool] = None self.interval: Optional[int] = None pass_config = click.make_pass_decorator(Config, ensure=True) # 替换为@click.command() @click.command() @click.option('-i', '--input-cv-file', type=click.Path(exists=True, dir_okay=False), help='Input CSV data file for cross-validation.') @click.option('-t', '--train-file', type=click.Path(exists=True, dir_okay=False), help='Train CSV data file.') @click.option('-e', '--test-file', type=click.Path(exists=True, dir_okay=False), help='Test CSV data file.') @click.option('-s', '--separator', type=click.STRING, default=',', show_default=True, help='Separator of the data files.') @click.option('-d', '--class-idx', type=click.IntRange(min=0), help='Class column index of the data files.') @click.option('-h', '--class-header', type=click.STRING, help='Class column header of the data files.') @click.option('-z', '--zero-replacement', type=click.FLOAT, default=1e-10, show_default=True, help='Zero values replacement.') @click.option('-r', '--reduction', type=click.IntRange(min=1), default=1, show_default=True, help='Dimensionality reduction.') @click.option('-p', '--percentage', type=click.FloatRange(min=0, max=1), multiple=True, help='Time-series percentage to be used for early prediction (multiple values can be given).') @click.option('-v', '--variate', type=click.IntRange(min=1), default=1, show_default=True, help='Number of series (attributes) per example.') @click.option('-g', '--strategy', type=click.Choice(['merge', 'vote', 'normal'], case_sensitive=False), help='Multi-variate training strategy.') @click.option('-f', '--folds', type=click.IntRange(min=2), default=5, show_default=True, help='Number of folds for cross-validation.') @click.option('-c', '--target-class', type=click.INT, help='Target class for computing counts. -1 stands for f1 for each class') @click.option('--java', is_flag=True, help='Algorithm implementation in java') @click.option('--cplus', is_flag=True, help='Algorithm implementation in C++') @click.option('--splits', type=click.Path(exists=True, dir_okay=False), help='Provided fold-indices file' ) @click.option('--make-cv', is_flag=True, help='If the dataset is divided and cross-validation is wanted' ) @click.option('-o', '--output', type=click.File(mode='w'), default='-', required=False, help='Results file (if not provided results shall be printed in the standard output).') @click.option('--realtime', is_flag=True, help="Activates the realtime mode in which the input of the data happens in real time. Requires parameter --interval") @click.option('--interval', default=100, help="Interval after how many milliseconds there will be a new datapoint") @pass_config def cli(config: Config, input_cv_file: click.Path, train_file: click.Path, test_file: click.Path, separator: str, class_idx: int, class_header: str, zero_replacement: float, reduction: int, percentage: List[float], variate: int, strategy: click.Choice, folds: int, target_class: int, java: bool, cplus: bool, splits: click.Path, output: click.File, make_cv: bool, realtime: bool, interval: int,) -> None: """ Library of Early Time-Series Classification algorithms. """ # Store generic parameters config.variate = variate config.strategy = strategy config.folds = folds config.target_class = target_class config.output = output config.java = java config.cplus = cplus config.splits = None config.make_cv = make_cv config.interval = interval config.realtime = realtime # 确保脚本可以直接运行 if __name__ == '__main__': cli()
方式二:需要子命令时
如果你的程序确实需要多个子命令,那么需要保留@click.group(),然后创建子命令来接收这些选项。例如:
from typing import Optional, List, Set, Dict import click import pandas as pd class Config(object): def __init__(self): self.cv_data: Optional[List[pd.DataFrame]] = None self.cv_labels: Optional[pd.DataFrame] = None self.train_data: Optional[List[pd.DataFrame]] = None self.train_labels: Optional[pd.DataFrame] = None self.test_data: Optional[List[pd.DataFrame]] = None self.test_labels: Optional[pd.DataFrame] = None self.classes: Optional[Set[int]] = None self.num_classes: Optional[int] = None self.ts_length: Optional[int] = None self.variate: Optional[int] = None self.strategy: Optional[str] = None self.timestamps: Optional[List[int]] = None self.folds: Optional[int] = None self.target_class: Optional[int] = None self.output: Optional[click.File] = None self.java: Optional[bool] = None self.file: Optional[click.File] = None self.splits: Optional[dict] = None self.make_cv: Optional[bool] = None self.realtime: Optional[bool] = None self.interval: Optional[int] = None pass_config = click.make_pass_decorator(Config, ensure=True) # 保留@click.group() @click.group() @click.option('--realtime', is_flag=True, help="Activates the realtime mode in which the input of the data happens in real time. Requires parameter --interval") @click.option('--interval', default=100, help="Interval after how many milliseconds there will be a new datapoint") @pass_config def cli(config: Config, realtime: bool, interval: int): config.realtime = realtime config.interval = interval # 添加子命令,比如run命令 @cli.command() @click.option('-i', '--input-cv-file', type=click.Path(exists=True, dir_okay=False), help='Input CSV data file for cross-validation.') @click.option('-t', '--train-file', type=click.Path(exists=True, dir_okay=False), help='Train CSV data file.') # 其他选项按需添加到子命令中 @pass_config def run(config: Config, input_cv_file: click.Path, train_file: click.Path): # 在这里编写业务逻辑 print(f"Realtime mode: {config.realtime}, Interval: {config.interval}") print(f"Input CV file: {input_cv_file}") if __name__ == '__main__': cli()
此时运行需要指定子命令,比如python your_script.py run --realtime --interval 200 -i data.csv。
内容的提问来源于stack exchange,提问作者user6346482
相关产品推荐
相关产品推荐

