pip install questionary
import questionary
name = questionary.text("请输入您的名字:").ask()
print(f"你好, {name}!")
message
(提示信息)、default
(默认值)、validate
(输入验证)。choice = questionary.select(
"请选择您喜欢的编程语言:",
choices=["Python", "JavaScript", "Java", "C++"]
).ask()
print(f"您选择了: {choice}")
choices
(选项列表)、qmark
(问题标记符号)。choices = questionary.checkbox(
"选择您使用的操作系统:",
choices=["Windows", "macOS", "Linux"]
).ask()
print(f"您选择了: {', '.join(choices)}")
confirmed = questionary.confirm("确定要删除文件吗?").ask()
if confirmed:
print("文件已删除")
else:
print("操作已取消")
True
或 False
。password = questionary.password("请输入密码:").ask()
print(f"密码已接收")
language = questionary.autocomplete(
"输入编程语言:",
choices=["Python", "PHP", "Perl", "JavaScript"],
).ask()
print(f"搜索语言: {language}")
questions = [
{"type": "text", "name": "name", "message": "您的名字?"},
{"type": "confirm", "name": "confirm", "message": "确认信息?"}
]
answers = questionary.prompt(questions)
print(answers)
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}")
import asyncio
async def main():
name = await questionary.text("您的名字?").async_ask()
print(f"Hello, {name}")
asyncio.run(main())
async_ask()
。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()
questionary.text(
"请输入项目名称:",
qmark="⚡", # 修改问题前缀符号
style=questionary.Style([
('qmark', 'fg:#FFA500 bold'), # 橙色加粗
('answer', 'fg:#008000 italic') # 绿色斜体
])
).ask()
qmark
修改问题标记,style
参数自定义颜色和字体样式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
限制仅选择文件questions = [
{"type": "text", "name": "name", "message": "姓名"},
{"type": "password", "name": "pwd", "message": "密码"},
{"type": "confirm", "name": "agree", "message": "接受协议?"}
]
answers = questionary.prompt(questions)
print(f"注册用户: {answers['name']}")
from rich import print
import questionary
name = questionary.text("输入用户名:").ask()
print(f"[bold green]✔ 用户 {name} 登录成功[/bold green]")
questionary
负责输入交互,rich
增强输出可视化效果import re
questionary.text(
"请输入邮箱地址:",
validate=lambda x: re.match(r"\S+@\S+\.\S+", x) or "格式无效"
).ask()
validate
参数实现正则验证,返回错误提示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())
动态问题流
when
参数控制问题显示条件混合交互类型
text
, select
, confirm
多种问题类型ProjectNameValidator
异步处理
async_ask()
进行异步提问美化输出
rich
库实现彩色输出和状态动画实际文件操作
项目初始化向导
项目名称: my_cli_project
? 项目类型: CLI工具
? 选择框架: Typer
添加文档支持? Yes
✅ 项目 my_cli_project 创建成功!
运行: cd my_cli_project
动态问题控制
when
参数实现条件分支lambda
函数访问之前的答案异步优化
async_ask()
避免阻塞asyncio.gather()
可并行处理多任务企业级验证
Validator
类创建复杂验证逻辑UI/UX 增强
rich
或 prompt-toolkit
扩展界面qmark
和 style
参数定制图标样式此示例展示了如何构建一个生产级 CLI 工具初始化流程,适合需要复杂交互的企业应用开发场景。