跳至主要内容

使用 GitHub Copilot 将项目迁移到另一种编程语言

GitHub Copilot Chat 可以帮助您将项目迁移到不同的语言。本指南描述了迁移过程涉及的内容,并提供了一个 PHP 到 Python 迁移的示例。

简介

将项目迁移到新编程语言可能是一个困难且耗时的任务。GitHub Copilot 可以通过解释您需要进行的更改并在新语言中提供替代代码建议来帮助您完成此过程。

将项目迁移到新语言的原则

在开始迁移过程之前,请考虑以下要点

  • 编码知识

    确保您对两种编程语言都有良好的理解。虽然 Copilot 可以为您翻译代码,但您需要了解它提出的选项,并决定是采用它的建议还是要求提供其他建议。

  • 了解您要迁移的系统

    确保您了解当前系统的架构和逻辑,以及它为用户提供的功能和特性。您必须能够检查翻译后的代码是否执行了原始代码的所有相同操作并产生相同的结果。

  • 使用 AI 来帮助您

    如果您不理解即将翻译的代码的某部分,请使用 Copilot 的“解释”功能,可对整个文件或文件中的选定代码段进行解释。参见在 IDE 中向 GitHub Copilot 提问

  • 为完成迁移安排时间

    转换是一个多阶段过程。项目越大,需要的步骤就越多。请确保为完成整个过程预留充足的时间。

  • 迭代工作

    目标是分别转换项目的离散部分。在继续迁移项目的其他部分之前,请确保已验证所有已完成的更改。随着进展,为项目的各个部分编写测试,以便确认每个新组件按预期工作。

  • 避免在流程中引入复杂性

    最初应尽量进行一对一的等价转换。并非所有代码都能实现此目标。但为避免在迁移任务中增加复杂度,您应尽量限制除代码翻译、使用新框架及相应依赖之外的其他更改数量。

  • 基准测试并重构翻译后的代码

    完成初始转换并拥有可工作的系统后,您可以进行基准测试,以比较新旧系统的性能。随后可以在新语言中重构代码,这是优化代码并降低技术债务的良机。

使用 Copilot 帮助您将项目迁移到新语言

假设您已经熟悉了现有项目,开始迁移的一个好方法是打开仓库的分支,在编辑器中请求 Copilot 的帮助。

  1. 在编辑器中打开 Copilot Chat 面板。参见在 IDE 中向 GitHub Copilot 提问

  2. 请 Copilot 列出将项目迁移到新语言所需的步骤。

    例如,要将项目从 PHP 迁移到 Python,您可以这样提问:

    Copilot 提示
    @workspace I want to migrate this project from PHP to Python. Give me a high-level overview of the steps I need to take. Don't go into detail at this stage.
    

    注意

    聊天参与者 @workspace 将当前工作区的文件设为您提问的上下文。

    Copilot 通常会返回一系列迁移项目所需完成的步骤。

  3. 复制 Copilot 的回复并将其保存,以便在整个过程中随时参考。

  4. 逐步完成每个步骤,必要时向 Copilot 请求详细帮助。

    仔细审视 Copilot 的每个建议。确保您理解它所建议的代码,并评估其是否适合您的项目。如果不确定,请让 Copilot 为您解释代码。

    如果您认为 Copilot 的某个建议有问题,请请求其他替代建议。

  5. 一旦将组件迁移到可运行的状态,请检查其是否按预期工作。如果出现错误,将错误信息复制到 Copilot Chat 视图中,并请 Copilot 帮助您修复。

  6. 完成初始转换后,使用 Copilot 帮助您在新语言中重构代码。更多信息请参见使用 GitHub Copilot 重构代码

示例:将 PHP 项目迁移到 Python

以下示例描述了将一个简单的 Web 应用程序从 PHP 迁移到 Python 的过程。即使这些编程语言并非您实际迁移时使用的语言,您也可以按照此处描述的步骤进行练习,以熟悉项目迁移。将其他小型项目从一种语言迁移到另一种语言的步骤大致相同。

Screenshot of the 'Simple PHP Website' prior to migration from PHP to Python.

本例假设

  • 您正在使用 Visual Studio Code。
  • 您已安装两种语言:PHP 和 Python(版本 3.12 或更高)。

迁移一个简单网站项目

我们将在 GitHub 上的公共仓库中迁移代码:docs/simple-php-website

该仓库包含以下文件。

.gitignore
.htaccess
LICENSE
content
├── 404.phtml
├── about-us.phtml
├── contact.phtml
├── home.phtml
└── products.phtml
includes
├── config.php
└── functions.php
index.php
readme.md
template
├── style.css
└── template.php

本示例给出了您可以在 Copilot Chat 中输入的提示,以完成迁移,以及 Copilot 为本次迁移实例返回的响应。使用的是 GPT‑4.1 模型。Copilot Chat 的响应具有非确定性,您实际得到的回复可能会略有不同。

在迁移过程中,您可能会遇到需要在继续前修复的错误。Copilot 可以帮助您解决这些问题。本示例包含了一些错误,并展示了如何让 Copilot 帮助您修复它们。

由于您从 Copilot Chat 获得的响应可能与此处显示的不同,您可能会遇到不同的错误。因此,您可能会发现使用此处展示的响应逐步演示示例迁移要比使用自己得到的响应更为便捷。

完成本示例迁移后,您即可在自己的项目上使用相同的方法。

  1. 首先将仓库克隆到本地机器。

  2. 运行应用程序以检查其是否正常工作。

    为此,请在终端中切换到克隆后仓库的根目录并执行以下命令:

    Shell
     php -S localhost:8000
    

    然后在浏览器中访问:https://:8000

  3. 在网站上随意点击,以熟悉其功能,从而能够验证迁移是否成功。

  4. 在仓库中创建一个工作分支,并在 Visual Studio Code 中将其作为新工作区打开。

  5. 熟悉现有项目的内容和架构。Copilot 可以帮助您完成此过程。

    1. 打开 Copilot Chat 视图。

    2. 输入类似以下的提示:

      Copilot 提示
      @workspace Describe this project in detail, explaining what the various components do and how they interact.
      
  6. 请 Copilot 提供迁移过程的高级概览

    Copilot 提示
    @workspace I want to migrate this project from PHP to Python. Give me a high-level overview of the steps I need to take. Don't go into detail at this stage.
    

    Copilot 会回复类似以下的指令:

    To migrate this project from PHP to Python, follow these high-level steps:
    
    1. Set Up Python Environment:
       - Install Python and set up a virtual environment.
       - Install necessary packages (e.g., Flask for web framework).
    
    2. Convert Configuration:
       - Translate the configuration settings from config.php to a Python configuration file.
    
    3. Rewrite Functions:
       - Convert PHP functions in functions.php to Python functions.
    
    4. Create Flask Application:
       - Set up a Flask application to handle routing and views.
       - Map the routes to corresponding views.
    
    5. Convert Templates:
       - Translate template.php to a Jinja2 template.
       - Update the CSS file path in the template.
    
    6. Convert Content Pages:
       - Convert .phtml content files to HTML or Jinja2 templates.
    
    7. Update .htaccess Rules:
       - Translate .htaccess rewrite rules to Flask route handling.
    
    8. Run and Test:
       - Run the Flask application and test all routes and functionalities.
       - Ensure the site works as expected and fix any issues.
    
    9. Documentation:
       - Update the readme.md with new instructions for running the Python project.
    
  7. 复制 Copilot 的回复并将其保存,以便在后续过程中随时参考。您将在每一步中按照这些指示进行,并在需要时向 Copilot 请求帮助。

  8. 如果您尚未决定使用哪种 Python 框架,可以向 Copilot 征求建议。

    Copilot 提示
    @workspace What Python frameworks can I use for this project once it is migrated to Python? Give me a selection of options, with a brief summary of the pros and cons of each in relation to this website project. Which framework would you recommend?
    

    Copilot 会提供各种框架的信息,并给出结论:

    For a project like yours - which is a simple, content-driven website - Flask is highly recommended. Its simplicity, flexibility, and ease of use (especially with its templating system that can easily replace your current PHP template structure) make it a great fit.
    

    我们将采纳 Copilot 的建议,使用 Flask。

  9. 回到 Copilot 的高级概览,第一步是设置 Python 环境并安装所需的包。要了解如何操作,请在 Copilot Chat 中输入:

    Copilot 提示
    @workspace I want to use Flask. Tell me how to set up a virtual environment and install the necessary packages.
    

    Copilot 会回复类似以下的指令:

    1. Create a virtual environment:
       - Open a terminal and navigate to your project directory.
       - Run the following command to create a virtual environment:
         python3 -m venv venv
    
    2. Activate the virtual environment:
       - On macOS and Linux:
         source venv/bin/activate
    
       - On Windows:
         venv\Scripts\activate
    
    3. Install Flask and necessary packages:
       - With the virtual environment activated, run the following command
         to install Flask and other necessary packages:
         pip install Flask
    
    4. Verify the installation:
       - You can verify that Flask is installed by running:
         pip list
    
  10. 按照 Copilot 的指示操作,并使用 pip list 验证 Flask 是否已安装。

  11. 回到迁移过程的概览,下一步是转换配置。请 Copilot 提供帮助,例如:

    Copilot 提示
    @workspace As the first step in migrating this project from PHP to Python, create a Python configuration file by converting the functions in functions.php to Python functions. Tell me where to locate the Python config file in the project.
    

    Copilot 建议您在 includes 目录下创建名为 config.py 的文件,内容如下。

    Python
    config = {
       'name': 'Simple Python Website',
       'site_url': '',
       'pretty_uri': False,
       'nav_menu': {
          '': 'Home',
          'about-us': 'About Us',
          'products': 'Products',
          'contact': 'Contact',
       },
      'template_path': 'template',
      'content_path': 'content',
      'version': 'v3.1',
    }
    
    def get_config(key=''):
       return config.get(key, None)
    
    def site_name():
       return get_config('name')
    
    def site_url():
       return get_config('site_url')
    
    def site_version():
       return get_config('version')
    
    def nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
    
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
    
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
    
       return nav_menu.strip(sep)
    
    def page_title():
       page = request.args.get('page', 'Home')
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def page_content():
       page = request.args.get('page', 'home')
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
    
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
    
       with open(path, 'r') as file:
          return file.read()
    
    def init():
       template_path = os.path.join(get_config('template_path'), 'template.html')
       with open(template_path, 'r') as file:
          return file.read()
    
  12. 创建 includes/config.py 文件并删除已有的 includes/config.php 文件。

  13. 再次回到概览,请 Copilot 帮助您重写 PHP 函数。

    Copilot 提示
    @workspace Continuing the migration of this project from PHP to Python, create Python functions to replace the existing PHP functions. Tell me where to locate the Python functions in the project.
    

    Copilot 建议在 includes 目录下创建名为 functions.py 的文件,内容如下。

    Python
    import os
    from flask import request
    from .config import get_config
    
    def site_name():
       return get_config('name')
    
    def site_url():
       return get_config('site_url')
    
    def site_version():
       return get_config('version')
    
    def nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
    
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
    
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
    
       return nav_menu.strip(sep)
    
    def page_title():
       page = request.args.get('page', 'Home')
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def page_content():
       page = request.args.get('page', 'home')
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
    
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
    
       with open(path, 'r') as file:
          return file.read()
    
    def init():
       template_path = os.path.join(get_config('template_path'), 'template.html')
       with open(template_path, 'r') as file:
          return file.read()
    
  14. 创建 includes/functions.py 文件并删除已有的 includes/functions.php 文件。

  15. 继续概览,下一步是创建 Flask 应用程序。请 Copilot 帮助您完成此操作。

    Copilot 提示
    @workspace Set up a Flask application to handle routing and views, and map the routes to corresponding views. Tell me the location of any files that need to be created or changed.
    

    Copilot 建议在项目根目录创建名为 app.py 的文件,内容如下。

    Python
    from flask import Flask, render_template, request
    import os
    
    app = Flask(__name__)
    
    config = {
       'name': 'Simple Python Website',
       'site_url': '',
       'pretty_uri': False,
       'nav_menu': {
          '': 'Home',
          'about-us': 'About Us',
          'products': 'Products',
          'contact': 'Contact',
       },
       'template_path': 'template',
       'content_path': 'content',
       'version': 'v3.1',
    }
    
    def get_config(key=''):
       return config.get(key, None)
    
    @app.route('/')
    @app.route('/<page>')
    def index(page='home'):
       page_content = get_page_content(page)
       page_title = get_page_title(page)
       nav_menu = get_nav_menu()
       return render_template('template.html', page_title=page_title, page_content=page_content, nav_menu=nav_menu)
    
    def get_page_title(page):
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def get_page_content(page):
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
       with open(path, 'r') as file:
          return file.read()
    
    def get_nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
       return nav_menu.strip(sep)
    
    if __name__ == '__main__':
       app.run(debug=True)
    

    Copilot 还建议将 template/template.php 重命名为 template/template.html,并将文件更新为使用 Jinja2 模板语法。

    HTML
    
    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8" />
       <meta http-equiv="x-ua-compatible" content="ie=edge"/>
       <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
       <title>{{ page_title }} | {{ get_config('name') }}</title>
       <link href="{{ get_config('site_url') }}/template/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
    <div class="wrap">
    
       <header>
          <h1>{{ get_config('name') }}</h1>
          <nav class="menu">
             {{ nav_menu|safe }}
          </nav>
       </header>
    
       <article>
          <h2>{{ page_title }}</h2>
          {{ page_content|safe }}
       </article>
    
       <footer>
          <small>&copy;{{ get_config('version') }} {{ get_config('name') }}.<br>{{ get_config('version') }}</small>
       </footer>
    
    </div>
    </body>
    </html>
    
    
  16. 按建议创建 app.pytemplate/template.html 文件。

  17. Copilot 可能还会建议,在创建这些文件后,您在终端(仓库根目录)运行 python app.py,然后在浏览器中访问 http://127.0.0.1:5000

    注意

    根据您电脑上 Python 的安装方式,可能需要使用 python3 app.py 而不是 python app.py,以确保使用正确的 Python 版本。

    执行后,您将在浏览器中看到错误信息。

  18. 将最初的 TemplateNotFound 错误信息复制到 Copilot Chat 视图,并询问如何修复。例如:

    Copilot 提示
    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.TemplateNotFound: template.html`. How can I fix this?
    

    Copilot 回答说该错误表明 Flask 无法定位 template.html 文件。

    它说明,默认情况下,Flask 会在项目根目录下名为 templates 的文件夹中查找模板。然而,您的 template.html 位于 template 目录中。为了解决此问题,需要在创建 Flask 应用时指定正确的模板文件夹。它建议您更新 app.py,将 app = Flask(__name__) 改为包含 template_folder 参数的形式。

    Python
    app = Flask(__name__, template_folder='template')
    
  19. 假设 Flask 开发服务器仍在运行,刷新浏览器页面 http://127.0.0.1:5000/,您将看到与 get_config 函数相关的新错误。

    将该错误信息复制到 Copilot Chat 视图并请求帮助。

    Copilot 提示
    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.UndefinedError: 'get_config' is undefined.` How can I fix this?
    

    Copilot 回答说错误是因为 get_config 未在 Jinja2 模板上下文中可用。它建议在 app.py 文件中、紧贴 @app.route('/') 行之前添加以下代码:

    Python
    app.jinja_env.globals.update(get_config=get_config)
    
  20. 刷新浏览器,您现在应该可以看到网站。

    Screenshot of the 'Simple Python Website' without CSS styling.

    但是,CSS 样式均未生效。我们接下来将解决此问题。

  21. 向 Copilot 提问

    Copilot 提示
    @workspace The deployed website does not use the CSS styles. How can I fix this?
    

    Copilot 告诉您 Flask 期望 CSS 文件位于名为 static 的目录中。它建议将现有的 style.csstemplate 目录移动到新建的 static 目录,并在 template.html 文件的 head 部分更新对 style.css 的路径。请将其改为:

    HTML
    
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    
    

    刷新浏览器后,网站应能够正常渲染。

    要完成初始迁移,请继续按照 Copilot 给出的高级概览中的步骤进行,必要时随时请求帮助。

完成迁移

要成功完成迁移过程,还需进行以下工作:

  • 彻底检查 初始迁移的完整性。
  • 错误修复。例如,在本示例中,页面链接仅在 app.py 文件的 config 部分将 pretty_uri 设置为 True 时才有效。如果您想在页面 URL 中使用查询字符串参数,或想从代码中移除此选项,可请求 Copilot 协助实现。
  • 为迁移后的项目编写测试
  • 清理项目,删除所有不再需要的文件。
  • 重构 新语言中的代码。迁移过程生成了一个基于原 PHP 项目架构的 Python 项目。完成初始迁移后,您可以对代码进行重构,以充分利用 Python 语言和 Flask 框架的特性。
  • 更新文档readme.md 文件已过时,需要重新编写。
© . This site is unofficial and not affiliated with GitHub, Inc.