」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何使用內省、點擊和豐富格式為 Python CLI 建立互動式聊天

如何使用內省、點擊和豐富格式為 Python CLI 建立互動式聊天

發佈於2024-11-08
瀏覽:113

How to Build an Interactive Chat for Your Python CLI Using Introspection, Click, and Rich Formatting

如果您曾经想让您的 CLI 更具交互性和动态性,构建实时命令交互系统可能是答案。通过利用 Python 的自省功能、用于管理命令的 Click 以及用于格式化输出的 Rich,您可以创建一个强大、灵活的 CLI,以智能地响应用户输入。您的 CLI 可以自动发现并执行命令,而不是手动对每个命令进行硬编码,从而使用户体验更流畅、更具吸引力。

多彩的控制台混乱:点击命令与丰富的输出相遇——因为即使是终端也喜欢炫耀风格!

为什么使用 Click 和 Markdown?

Click 简化了命令管理、参数解析和帮助生成。它还允许轻松的命令结构和选项处理。

Rich 使您能够直接在终端中输出格式精美的 Markdown,使结果不仅实用,而且具有视觉吸引力。

通过将这两个库与 Python 自省相结合,您可以构建交互式聊天功能,该功能可以动态发现和执行命令,同时以丰富、可读的格式显示输出。 有关实际示例,请了解 StoryCraftr 如何使用类似的方法来简化 AI 驱动的写作工作流程: https://storycraftr.app.

构建互动聊天系统

1. 设置基本聊天命令

chat 命令初始化会话,允许用户与 CLI 交互。在这里,我们捕获用户输入,这些输入将动态映射到适当的单击命令。

import os
import click
import shlex
from rich.console import Console
from rich.markdown import Markdown

console = Console()

@click.command()
@click.option("--project-path", type=click.Path(), help="Path to the project directory")
def chat(project_path=None):
    """
    Start a chat session with the assistant for the given project.
    """
    if not project_path:
        project_path = os.getcwd()

    console.print(
        f"Starting chat for [bold]{project_path}[/bold]. Type [bold green]exit()[/bold green] to quit."
    )

    # Start the interactive session
    while True:
        user_input = console.input("[bold blue]You:[/bold blue] ")

        # Handle exit
        if user_input.lower() == "exit()":
            console.print("[bold red]Exiting chat...[/bold red]")
            break

        # Call the function to handle command execution
        execute_cli_command(user_input)

2. 自省以发现和执行命令

使用Python内省,我们动态地发现可用的命令并执行它们。这里的一个关键部分是 Click 命令是修饰函数。为了执行实际的逻辑,我们需要调用未修饰的函数(即回调)。

以下是如何使用内省动态执行命令并处理 Click 的装饰器:

import inspect
import your_project_cmd  # Replace with your actual module containing commands

command_modules = {"project": your_project_cmd}  # List your command modules here

def execute_cli_command(user_input):
    """
    Function to execute CLI commands dynamically based on the available modules,
    calling the undecorated function directly.
    """
    try:
        # Use shlex.split to handle quotes and separate arguments correctly
        parts = shlex.split(user_input)
        module_name = parts[0]
        command_name = parts[1].replace("-", "_")  # Replace hyphens with underscores
        command_args = parts[2:]  # Keep the rest of the arguments as a list

        # Check if the module exists in command_modules
        if module_name in command_modules:
            module = command_modules[module_name]

            # Introspection: Get the function by name
            if hasattr(module, command_name):
                cmd_func = getattr(module, command_name)

                # Check if it's a Click command and strip the decorator
                if hasattr(cmd_func, "callback"):
                    # Call the underlying undecorated function
                    cmd_func = cmd_func.callback

                # Check if it's a callable (function)
                if callable(cmd_func):
                    console.print(
                        f"Executing command from module: [bold]{module_name}[/bold]"
                    )

                    # Directly call the function with the argument list
                    cmd_func(*command_args)
                else:
                    console.print(
                        f"[bold red]'{command_name}' is not a valid command[/bold red]"
                    )
            else:
                console.print(
                    f"[bold red]Command '{command_name}' not found in {module_name}[/bold red]"
                )
        else:
            console.print(f"[bold red]Module {module_name} not found[/bold red]")
    except Exception as e:
        console.print(f"[bold red]Error executing command: {str(e)}[/bold red]")

这是如何运作的?

  • 输入解析:我们使用 shlex.split 来处理命令行参数等输入。这可确保正确处理带引号的字符串和特殊字符。
  • 模块和命令查找:输入分为 module_name 和 command_name。命令名称经过处理,将连字符替换为下划线,以匹配 Python 函数名称。
  • 内省:我们使用 getattr() 从模块动态获取命令函数。如果它是一个 Click 命令(即具有回调属性),我们通过剥离 Click 装饰器来访问实际的函数逻辑。
  • 命令执行:一旦我们检索到未修饰的函数,我们就传递参数并调用它,就像我们直接调用Python函数一样。

3. CLI 命令示例

让我们考虑项目模块中的一些示例命令,用户可以通过聊天交互调用这些命令:

@click.group()
def project():
    """Project management CLI."""
    pass

@project.command()
def init():
    """Initialize a new project."""
    console.print("[bold green]Project initialized![/bold green]")

@project.command()
@click.argument("name")
def create(name):
    """Create a new component in the project."""
    console.print(f"[bold cyan]Component {name} created.[/bold cyan]")

@project.command()
def status():
    """Check the project status."""
    console.print("[bold yellow]All systems operational.[/bold yellow]")

执行聊天界面

运行交互式聊天系统:

  1. 确保您的模块(如项目)已在 command_modules 中列出。
  2. 运行命令:
python your_cli.py chat --project-path /path/to/project

会话开始后,用户可以输入以下命令:

You: project init You: project create "Homepage"

输出将使用 Rich Markdown 以格式良好的方式显示:

[bold green]Project initialized![/bold green] [bold cyan]Component Homepage created.[/bold cyan]

结论

通过结合 Click 命令管理、Rich for Markdown 格式和 Python 自省,我们可以为 CLI 构建一个强大的交互式聊天系统。这种方法允许您动态发现和执行命令,同时以优雅、可读的格式呈现输出。

主要亮点:

  • 动态命令执行:内省使您能够发现和运行命令,而无需对其进行硬编码。
  • 丰富的输出:使用丰富的 Markdown 可确保输出易于阅读且具有视觉吸引力。
  • 灵活性:此设置允许命令结构和执行的灵活性。
版本聲明 本文轉載於:https://dev.to/rodrigo_estrada_79e6022e9/how-to-build-an-interactive-chat-for-your-python-cli-using-introspection-click-and-rich-formatting-4l9a?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何確定 C++ 中動態分配數組的大小?
    如何確定 C++ 中動態分配數組的大小?
    在C 中動態分配後確定數組大小在C 中,使用new 運算子動態分配的數組本質上不會以程式設計方式公開其大小。這個問題源自於這樣的觀察:delete[] 必須知道分配的陣列的大小才能有效地釋放記憶體。 為什麼沒有內建函數來取得陣列大小? 與在堆疊上聲明的數組不同,其大小可以使用 sizeof() 確定...
    程式設計 發佈於2024-11-09
  • Nginx 在 https 埠上強制 http 轉為 https
    Nginx 在 https 埠上強制 http 轉為 https
    範例腳本 nginx : server { listen 443 default ssl; listen [::]:443 ssl; root /var/www/html/api_mobile/public; include snip...
    程式設計 發佈於2024-11-09
  • 解決 PHP 中的命名空間問題:為什麼找不到類別?
    解決 PHP 中的命名空間問題:為什麼找不到類別?
    解決 PHP 自動載入的命名空間問題在 PHP 中使用命名空間和自動載入機制時,經常會遇到無法找到所需類別的錯誤。讓我們探討一下這個錯誤背後的原因並提供解決方案。 如提供的程式碼片段所示,出現錯誤「Class 'Class1' not found」是因為 Class1 類別未在全域範...
    程式設計 發佈於2024-11-09
  • 如何輕鬆將 JavaScript 陣列轉換為逗號分隔清單?
    如何輕鬆將 JavaScript 陣列轉換為逗號分隔清單?
    提升JavaScript:輕鬆將陣列轉換為逗號分隔清單在JavaScript 中處理陣列時,將它們轉換為可讀格式像逗號分隔的清單通常是常見任務。有一個巧妙的方法可以輕鬆實現此目的,而不是訴諸手動字串連接。 Array.prototype.join() 方法介紹陣列。 prototype.join()...
    程式設計 發佈於2024-11-09
  • Java Sound 可以播放 MP3 檔案嗎?
    Java Sound 可以播放 MP3 檔案嗎?
    Java Sound 預設不支援 MP3。對於特定 JRE 中支援的類型,請檢查 AudioSystem.getAudioFileTypes()。 有一種方法可以加入 MP3 支援。將基於 JMF 的 mp3plugin.jar 加入到專案的執行時間類別路徑中。 雖然 javax.sound.sam...
    程式設計 發佈於2024-11-09
  • 如何在 Socket.IO 中阻止發送方接收回應?
    如何在 Socket.IO 中阻止發送方接收回應?
    如何在 Socket.IO 中向發送者以外的所有客戶端發送回應? Socket.IO 提供了一系列的通訊方法用戶端和伺服器。要將訊息傳送到所有客戶端,可以使用 io.sockets.emit('response', data);。但是,當您需要排除發送客戶端接收回應時,這種方法就不夠...
    程式設計 發佈於2024-11-09
  • 如何在 Go 中使用即時請求測試 HTTP 伺服器?
    如何在 Go 中使用即時請求測試 HTTP 伺服器?
    在Go 中使用即時請求測試HTTP 伺服器獨立的單元測試處理程序至關重要,但可能忽略路由和其他中間件的影響。對於全面的測試,請考慮使用“實時伺服器”方法。 使用 httptest.Server 進行即時伺服器測試net/http/httptest.Server 類型有助於即時伺服器測試。它使用提供的...
    程式設計 發佈於2024-11-09
  • 如何在添加數據時自動滾動 Div 到末尾?
    如何在添加數據時自動滾動 Div 到末尾?
    如何在新增資料時自動捲動至Div 的結尾處理動態Web 內容時,通常希望讓div 等元素自動捲動到新增資料時的底部。這是聊天視窗或無限滾動資料表等元素的常見要求。 考慮這樣一個場景:您有一個表格包含在固定高度的 div 中,並且您希望它自動滾動到末尾當添加新資料時。本文探討了實作此行為的 JavaS...
    程式設計 發佈於2024-11-09
  • 如何使用 Laravel Eloquent 取得每個賣家的最新快照?
    如何使用 Laravel Eloquent 取得每個賣家的最新快照?
    用於選擇按賣家分組的最新行的雄辯查詢給定一個包含賣家相關資訊(包括created_at時間戳)的表,通常需要僅檢索每個賣家的最新條目。使用 Laravel Eloquent 可以有效地完成此任務。 為了實現這一目標,我們可以使用 MySQL 子查詢,該子查詢使用左連接和 NULL 匹配來標識每個 s...
    程式設計 發佈於2024-11-09
  • 如何去掉 Go 時間戳記中的「m」字尾?
    如何去掉 Go 時間戳記中的「m」字尾?
    如何在Go 時間戳中排除“m”指示符在Go 中,time.Now() 函數返回一個帶有尾隨“m”後綴表示單調時鐘讀數。對於不需要的特定用例,可以刪除此後綴。 「m」的意思「m」字尾表示掛鐘之間的距離和單調時鐘讀數,以十進位秒錶示。調整掛鐘以保持與外部來源的精確計時,同時單調時鐘穩定遞增而不中斷。 刪...
    程式設計 發佈於2024-11-09
  • 如何安裝和使用Django
    如何安裝和使用Django
    姜戈 Django 是免費開源用Python編寫的網路架構。它遵循模型-模板-視圖架構模式,並由Django 軟體基金會維護。它於 2005 年 7 月 21 日首次發布,並根據 3 條款 BSD 許可證獲得許可。 Django 以其快速開發和乾淨、務實的設計而聞名,使其成為建立 ...
    程式設計 發佈於2024-11-09
  • 有趣的彩色 Codepen
    有趣的彩色 Codepen
    嗨,身為設計師,色彩對我來說真的很重要。 在過去的兩年裡,我收集並創建了一些調色板。但這不是今天貼文的主題。 今天我想分享一些我製作的有趣的彩色筆。 我們走吧… (注意:其中一些可能在行動裝置上不相容。) 1. RGB 顏色滑桿 對此我能說什麼。首先,在我們進一步討論之前,我應...
    程式設計 發佈於2024-11-09
  • 為什麼我無法更改 IE8 中禁用的 HTML 控制項的文字顏色?
    為什麼我無法更改 IE8 中禁用的 HTML 控制項的文字顏色?
    IE8 中禁用的HTML 控制項的CSS 顏色變更問題在HTML 中,disabled 屬性停用輸入控制項,但它也會影響控制項這些控制項的外觀。大多數瀏覽器都支援使用 CSS 套用於停用控制項的自訂樣式。然而,Internet Explorer 8 (IE8) 在更改停用控制項的顏色方面提出了獨特的...
    程式設計 發佈於2024-11-09
  • React 中的純元件:釋放效能
    React 中的純元件:釋放效能
    在现代 React 开发中,性能通常是一个关键焦点,尤其是当应用程序变得越来越复杂时。优化性能最有效的方法之一是利用 React 中的纯组件。 Pure Components 提供强大的优化技术,减少不必要的重新渲染,并确保您的应用程序运行得更快、更流畅。在这篇博客中,我们将深入探讨纯组件是什么、何...
    程式設計 發佈於2024-11-09
  • 引用計數與追蹤垃圾收集
    引用計數與追蹤垃圾收集
    你好,Mentes Tech! 您知道記憶體釋放上下文中的引用計數和引用追蹤是什麼嗎? 引用追蹤(或追蹤垃圾收集)和引用計數(引用計數)之間的區別在於每種技術用於識別和釋放不存在的物件記憶體的方法。使用時間更長。 我將解釋每一個,然後強調主要差異。 引用計數(引用計數) 工作...
    程式設計 發佈於2024-11-09

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3