【python】questionary库入门与代码示例

具体使用

1. 安装
pip install questionary

2. 基本输入 (Text Input)
import questionary

name = questionary.text("请输入您的名字:").ask()
print(f"你好, {name}!")
  • 功能‌:获取用户输入的文本。
  • 常用参数‌:message(提示信息)、default(默认值)、validate(输入验证)。

3. 单选列表 (Select)
choice = questionary.select(
    "请选择您喜欢的编程语言:",
    choices=["Python", "JavaScript", "Java", "C++"]
).ask()
print(f"您选择了: {choice}")
  • 功能‌:从列表中选择一个选项。
  • 常用参数‌:choices(选项列表)、qmark(问题标记符号)。

4. 多选列表 (Checkbox)
choices = questionary.checkbox(
    "选择您使用的操作系统:",
    choices=["Windows", "macOS", "Linux"]
).ask()
print(f"您选择了: {', '.join(choices)}")
  • 功能‌:允许用户选择多个选项。
  • 注意‌:返回一个列表。

5. 确认对话框 (Confirm)
confirmed = questionary.confirm("确定要删除文件吗?").ask()
if confirmed:
    print("文件已删除")
else:
    print("操作已取消")
  • 功能‌:返回 TrueFalse

6. 密码输入 (Password)
password = questionary.password("请输入密码:").ask()
print(f"密码已接收")
  • 功能‌:隐藏用户输入内容(显示为星号)。

7. 自动补全输入 (Autocomplete)
language = questionary.autocomplete(
    "输入编程语言:",
    choices=["Python", "PHP", "Perl", "JavaScript"],
).ask()
print(f"搜索语言: {language}")
  • 功能‌:输入时自动匹配选项。
  • 注意‌:用户也可以输入未列出的内容。

8. 链式调用 (Chained Questions)
questions = [
    {"type": "text", "name": "name", "message": "您的名字?"},
    {"type": "confirm", "name": "confirm", "message": "确认信息?"}
]

answers = questionary.prompt(questions)
print(answers)
  • 功能‌:通过字典列表定义多个连续问题。

9. 输入验证 (Validation)
def validate_age(age):
    if not age.isdigit():
        return "请输入数字"
    if int(age) < 18:
        return "年龄必须大于18岁"
    return True

age = questionary.text(
    "请输入您的年龄:", 
    validate=validate_age
).ask()
print(f"年龄: {age}")
  • 功能‌:自定义验证函数确保输入合法。

10. 异步支持 (Async)
import asyncio

async def main():
    name = await questionary.text("您的名字?").async_ask()
    print(f"Hello, {name}")

asyncio.run(main())
  • 功能‌:在异步代码中使用 async_ask()

中级应用

1. 动态问题生成(根据前置答案调整后续问题)

import questionary

# 第一步:选择用户角色
role = questionary.select(
    "选择您的角色:", 
    choices=["开发者", "测试工程师", "运维人员"]
).ask()  # ‌:ml-citation{ref="2" data="citationList"}

# 第二步:动态生成问题
if role == "开发者":
    lang = questionary.checkbox(
        "您使用的编程语言:", 
        choices=["Python", "Java", "Go"]
    ).ask()
elif role == "运维人员":
    tool = questionary.confirm("是否使用 Kubernetes?").ask()
  • 解析‌:通过前置问题结果动态调整后续问题类型
  • 应用场景‌:多步骤表单、个性化配置工具

2. 自定义交互样式

questionary.text(
    "请输入项目名称:",
    qmark="⚡",  # 修改问题前缀符号
    style=questionary.Style([
        ('qmark', 'fg:#FFA500 bold'),  # 橙色加粗
        ('answer', 'fg:#008000 italic')  # 绿色斜体
    ])
).ask()
  • 解析‌:通过 qmark 修改问题标记,style 参数自定义颜色和字体样式
  • 扩展能力‌:支持 ANSI 颜色代码和样式组合 ‌

3. 文件路径选择与验证

def validate_path(path):
    if not path.endswith(".json"):
        return "必须为 JSON 文件"
    return True

file_path = questionary.path(
    "请输入配置文件路径:",
    default="config.json",
    validate=validate_path,
    only_files=True  # 仅允许选择文件
).ask()
  • 解析‌:path 类型专用于文件/目录选择,only_files 限制仅选择文件
  • 典型用途‌:CLI 工具配置文件管理 ‌

4. 分页式复杂表单

questions = [
    {"type": "text", "name": "name", "message": "姓名"},
    {"type": "password", "name": "pwd", "message": "密码"},
    {"type": "confirm", "name": "agree", "message": "接受协议?"}
]
answers = questionary.prompt(questions)
print(f"注册用户: {answers['name']}")
  • 解析‌:通过字典列表定义多步骤问题,自动按顺序执行
  • 优势‌:代码结构清晰,便于维护复杂交互流程 ‌

5. 与 Rich 库结合实现彩色输出

from rich import print
import questionary

name = questionary.text("输入用户名:").ask()
print(f"[bold green]✔ 用户 {name} 登录成功[/bold green]")
  • 解析‌:questionary 负责输入交互,rich 增强输出可视化效果
  • 组合价值‌:构建专业级命令行工具界面 ‌

6. 高级输入验证(正则表达式)

import re

questionary.text(
    "请输入邮箱地址:",
    validate=lambda x: re.match(r"\S+@\S+\.\S+", x) or "格式无效"
).ask()
  • 解析‌:通过 validate 参数实现正则验证,返回错误提示
  • 安全场景‌:数据录入合法性校验 ‌

7. 条件跳转问题流

has_account = questionary.confirm("是否已有账户?").ask()
if not has_account:
    questionary.text("请输入手机号:").ask()
    questionary.password("设置密码:").ask()
else:
    questionary.text("输入手机号:").ask()
    questionary.password("输入密码:").ask()
  • 解析‌:通过 confirm 类型控制问题分支逻辑
  • 业务场景‌:登录/注册流程切换 ‌

高级应用

高级示例:项目初始化向导
python
Copy Code
import os
import asyncio
from pathlib import Path
import questionary
from questionary import Validator, ValidationError
from rich.console import Console

# 自定义验证器:检查项目名称合法性
class ProjectNameValidator(Validator):
    def validate(self, value):
        if not value.strip():
            raise ValidationError(message="项目名称不能为空")
        if not value.isidentifier():
            raise ValidationError(message="必须是合法Python标识符")
        if Path(value).exists():
            raise ValidationError(message="目录已存在")

# 异步生成配置文件
async def generate_config(answers):
    await asyncio.sleep(1)  # 模拟耗时操作
    config = f"""
    [project]
    name = {answers['name']}
    type = {answers['type']}
    framework = {answers.get('framework', 'none')}
    """
    Path(f"{answers['name']}/config.ini").write_text(config)

# 主流程
async def main():
    console = Console()
    console.print("[bold cyan]🐍 项目初始化向导[/bold cyan]\n")

    # 动态问题流
    answers = await questionary.prompt([
        {
            'type': 'text',
            'name': 'name',
            'message': '项目名称',
            'validate': ProjectNameValidator,
            'qmark': '🔧'
        },
        {
            'type': 'select',
            'name': 'type',
            'message': '项目类型',
            'choices': ['Web应用', 'CLI工具', '数据分析'],
            'when': lambda ans: ans['name'] is not None
        },
        {
            'type': 'select',
            'name': 'framework',
            'message': '选择框架',
            'choices': lambda ans: 
                ['Django', 'Flask'] if ans['type'] == 'Web应用' 
                else ['Typer', 'Click'],
            'when': lambda ans: ans['type'] in ['Web应用', 'CLI工具']
        },
        {
            'type': 'confirm',
            'name': 'add_docs',
            'message': '添加文档支持?',
            'default': True,
            'qmark': '📚'
        }
    ]).async_ask()

    # 生成文件
    with console.status("[bold green]生成项目中..."):
        await generate_config(answers)
    
    console.print(f"\n[bold green]✅ 项目 {answers['name']} 创建成功![/bold green]")
    console.print(f"👉 运行: [code]cd {answers['name']}[/code]")

if __name__ == "__main__":
    asyncio.run(main())


功能解析

  1. 动态问题流

    • 使用 when 参数控制问题显示条件
    • 当选择 “Web应用” 时显示框架选项,其他类型显示不同选项
    • 项目名称验证失败自动重新提问
  2. 混合交互类型

    • 结合 text, select, confirm 多种问题类型
    • 使用自定义验证器 ProjectNameValidator
  3. 异步处理

    • 使用 async_ask() 进行异步提问
    • 文件生成时显示加载状态指示器
  4. 美化输出

    • 集成 rich 库实现彩色输出和状态动画
    • 使用表情符号图标增强可读性
  5. 实际文件操作

    • 根据用户输入生成配置文件
    • 检查目录是否存在避免覆盖


🐍 项目初始化向导

🔧 项目名称: my_cli_project
? 项目类型: CLI工具
? 选择框架: Typer
📚 添加文档支持? Yes

✅ 项目 my_cli_project 创建成功!
👉 运行: cd my_cli_project

高级技巧总结

  1. 动态问题控制

    • 使用 when 参数实现条件分支
    • 通过 lambda 函数访问之前的答案
  2. 异步优化

    • 在长时间操作中使用 async_ask() 避免阻塞
    • 结合 asyncio.gather() 可并行处理多任务
  3. 企业级验证

    • 继承 Validator 类创建复杂验证逻辑
    • 可集成数据库检查等外部验证
  4. UI/UX 增强

    • 使用 richprompt-toolkit 扩展界面
    • 通过 qmarkstyle 参数定制图标样式

此示例展示了如何构建一个生产级 CLI 工具初始化流程,适合需要复杂交互的企业应用开发场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔都吴所谓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值