python 进阶,如何用胶水一样用别人的半成品快速完成项目,附带git操作流程,超简单

查看 47|回复 4
作者:zigzag   
我们都知道,,,python是个胶水语言,怎么用别人的半成品快速的改个皮肤或者借鉴跑通业务逻辑呢。
当然是拷贝,克隆别人公开源代码啦。。。
第一步,https://git-scm.com/downloads  根据系统版本,下载对应的git
第二步,打开github,看到自己感兴趣或者业务逻辑相符合大的,并筛选是python写的,优秀的项目,
  
点绿色code  复制代码
第三步,执行我写的程序粘贴,(代理自己找一个,,因为github服务器距离我们较远,频繁抽风),然后点击"执行 Git Clone“
第四步,点克隆,并右击PyCharm   "Open Folder as PyCharm Project"   创建一个虚拟环境的python,就可以啦
附录
[Python] 纯文本查看 复制代码import sys
import os
import subprocess
import threading
import json
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QLabel, QLineEdit, QTextEdit, QPushButton, QCheckBox,
                             QGroupBox, QComboBox, QFileDialog, QMessageBox, QProgressBar,
                             QSplitter, QFrame, QScrollArea, QStyle)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSettings, QUrl
from PyQt5.QtGui import QFont, QPalette, QIcon, QDesktopServices
class CloneThread(QThread):
    """克隆线程"""
    output_signal = pyqtSignal(str)
    finished_signal = pyqtSignal(bool, str)
    def __init__(self, url, target_dir, use_proxy, proxy_url):
        super().__init__()
        self.url = url
        self.target_dir = target_dir
        self.use_proxy = use_proxy
        self.proxy_url = proxy_url
        self.is_running = True
    def run(self):
        try:
            # 设置代理
            if self.use_proxy and self.proxy_url:
                self.output_signal.emit(f"设置代理: {self.prsoxy_url}\n")
                try:
                    subprocess.run(['git', 'config', '--global', 'http.proxy', self.proxy_url],
                                   check=True, capture_output=True, text=True)
                    subprocess.run(['git', 'config', '--global', 'https.proxy', self.proxy_url],
                                   check=True, capture_output=True, text=True)
                except subprocess.CalledProcessError as e:
                    self.output_signal.emit(f"设置代理失败: {e}\n")
            # 执行git clone
            self.output_signal.emit(f"开始克隆: {self.url}\n")
            self.output_signal.emit(f"目标目录: {self.target_dir}\n")
            self.output_signal.emit("-" * 50 + "\n")
            # 确保目标目录存在
            os.makedirs(self.target_dir, exist_ok=True)
            # 切换到目标目录执行clone
            original_dir = os.getcwd()
            os.chdir(self.target_dir)
            process = subprocess.Popen(['git', 'clone', self.url],
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.STDOUT,
                                       text=True,
                                       bufsize=1,
                                       universal_newlines=True)
            # 实时输出
            while self.is_running:
                line = process.stdout.readline()
                if not line:
                    break
                self.output_signal.emit(line)
            process.wait()
            os.chdir(original_dir)
            if process.returncode == 0:
                self.output_signal.emit("\n✅ 克隆完成!\n")
                self.finished_signal.emit(True, "克隆完成")
            else:
                self.output_signal.emit(f"\n❌ 克隆失败,返回码: {process.returncode}\n")
                self.finished_signal.emit(False, "克隆失败")
        except Exception as e:
            self.output_signal.emit(f"❌ 发生错误: {str(e)}\n")
            self.finished_signal.emit(False, f"发生错误: {str(e)}")
    def stop(self):
        self.is_running = False
class GitCloneGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.settings = QSettings("GitCloneTool", "Config")
        self.clone_thread = None
        self.init_ui()
        self.load_settings()
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("Git Clone 工具 - PyQt5版")
        self.setGeometry(100, 100, 900, 700)
        # 设置样式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QGroupBox {
                font-weight: bold;
                margin-top: 1ex;
                border: 1px solid #cccccc;
                border-radius: 5px;
                padding-top: 10px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px 0 5px;
            }
            QPushButton {
                background-color: #007acc;
                color: white;
                border: none;
                padding: 8px 15px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #005a9e;
            }
            QPushButton:disabled {
                background-color: #cccccc;
                color: #666666;
            }
            QPushButton#success {
                background-color: #28a745;
            }
            QPushButton#danger {
                background-color: #dc3545;
            }
            QTextEdit {
                border: 1px solid #cccccc;
                border-radius: 4px;
                padding: 5px;
                font-family: 'Consolas', 'Monaco', monospace;
            }
            QLineEdit, QComboBox {
                padding: 6px;
                border: 1px solid #cccccc;
                border-radius: 4px;
            }
            QProgressBar {
                border: 1px solid #cccccc;
                border-radius: 4px;
                text-align: center;
            }
            QProgressBar::chunk {
                background-color: #007acc;
                width: 20px;
            }
        """)
        # 创建中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setSpacing(15)
        main_layout.setContentsMargins(20, 20, 20, 20)
        # 代理设置组
        self.create_proxy_group(main_layout)
        # URL输入组
        self.create_url_group(main_layout)
        # 目录设置组
        self.create_directory_group(main_layout)
        # 按钮组
        self.create_button_group(main_layout)
        # 输出区域
        self.create_output_group(main_layout)
        # 状态栏
        self.create_status_bar()
        self.set_random_icon()
    def create_proxy_group(self, layout):
        """创建代理设置组"""
        proxy_group = QGroupBox("代理设置")
        proxy_layout = QHBoxLayout()
        # 代理历史选择
        proxy_layout.addWidget(QLabel("代理地址:"))
        self.proxy_combo = QComboBox()
        self.proxy_combo.setEditable(True)
        self.proxy_combo.setMinimumWidth(300)
        proxy_layout.addWidget(self.proxy_combo)
        # 启用代理复选框
        self.use_proxy_check = QCheckBox("启用代理")
        self.use_proxy_check.setChecked(True)
        proxy_layout.addWidget(self.use_proxy_check)
        # 保存代理按钮
        self.save_proxy_btn = QPushButton("保存代理")
        self.save_proxy_btn.clicked.connect(self.save_proxy_to_history)
        proxy_layout.addWidget(self.save_proxy_btn)
        # 清除代理历史按钮
        self.clear_proxy_btn = QPushButton("清除历史")
        self.clear_proxy_btn.setObjectName("danger")
        self.clear_proxy_btn.clicked.connect(self.clear_proxy_history)
        proxy_layout.addWidget(self.clear_proxy_btn)
        proxy_layout.addStretch()
        proxy_group.setLayout(proxy_layout)
        layout.addWidget(proxy_group)
    def create_url_group(self, layout):
        """创建URL输入组"""
        url_group = QGroupBox("Git 仓库地址")
        url_layout = QVBoxLayout()
        # URL输入框
        self.url_input = QTextEdit()
        self.url_input.setMaximumHeight(80)
        self.url_input.setPlaceholderText(
            "输入Git仓库URL,例如:\nhttps://github.com/jark006/FtpServer.git\n或者完整的 git clone 命令")
        url_layout.addWidget(self.url_input)
        # 示例按钮区域隐藏
        # (已移除快速示例按钮以保持界面简洁)
        url_group.setLayout(url_layout)
        layout.addWidget(url_group)
    def create_directory_group(self, layout):
        """创建目录设置组"""
        dir_group = QGroupBox("输出目录设置")
        dir_layout = QHBoxLayout()
        dir_layout.addWidget(QLabel("保存路径:"))
        self.dir_input = QLineEdit()
        self.dir_input.setText("D:\\clone")
        dir_layout.addWidget(self.dir_input)
        self.browse_btn = QPushButton("浏览")
        self.browse_btn.clicked.connect(self.browse_directory)
        dir_layout.addWidget(self.browse_btn)
        # 设置默认目录按钮
        self.set_default_btn = QPushButton("设为默认")
        self.set_default_btn.clicked.connect(self.set_default_directory)
        dir_layout.addWidget(self.set_default_btn)
        dir_group.setLayout(dir_layout)
        layout.addWidget(dir_group)
    def create_button_group(self, layout):
        """创建按钮组"""
        button_layout = QHBoxLayout()
        self.clone_btn = QPushButton("🚀 执行 Git Clone")
        self.clone_btn.clicked.connect(self.start_clone)
        self.clone_btn.setMinimumHeight(40)
        button_layout.addWidget(self.clone_btn)
        self.clear_btn = QPushButton("🗑️ 清空")
        self.clear_btn.clicked.connect(self.clear_input)
        self.clear_btn.setMinimumHeight(40)
        button_layout.addWidget(self.clear_btn)
        self.stop_btn = QPushButton("⏹️ 停止")
        self.stop_btn.clicked.connect(self.stop_clone)
        self.stop_btn.setMinimumHeight(40)
        self.stop_btn.setEnabled(False)
        button_layout.addWidget(self.stop_btn)
        self.open_dir_btn = QPushButton("📂 打开克隆位置")
        self.open_dir_btn.clicked.connect(self.open_clone_location)
        self.open_dir_btn.setMinimumHeight(40)
        button_layout.addWidget(self.open_dir_btn)
        # self.random_icon_btn = QPushButton("🎲 随机图标")
        # self.random_icon_btn.setMinimumHeight(40)
        # self.random_icon_btn.clicked.connect(self.set_random_icon)
        # button_layout.addWidget(self.random_icon_btn)
        layout.addLayout(button_layout)
    def create_output_group(self, layout):
        """创建输出区域"""
        output_group = QGroupBox("输出信息")
        output_layout = QVBoxLayout()
        self.output_text = QTextEdit()
        self.output_text.setReadOnly(True)
        self.output_text.setFont(QFont("Consolas", 9))
        output_layout.addWidget(self.output_text)
        output_group.setLayout(output_layout)
        layout.addWidget(output_group)
    def create_status_bar(self):
        """创建状态栏"""
        self.status_bar = self.statusBar()
        self.status_label = QLabel("就绪")
        self.status_bar.addWidget(self.status_label)
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setMaximumWidth(200)
        self.progress_bar.setVisible(False)
        self.status_bar.addPermanentWidget(self.progress_bar)
    def set_random_icon(self):
        """随机设置窗口图标(使用Qt内置标准图标)"""
        try:
            candidates = [
                QStyle.SP_ComputerIcon,
                QStyle.SP_DesktopIcon,
                QStyle.SP_DriveHDIcon,
                QStyle.SP_DirIcon,
                QStyle.SP_DirHomeIcon,
                QStyle.SP_DirOpenIcon,
                QStyle.SP_FileIcon,
                QStyle.SP_TrashIcon,
                QStyle.SP_DialogOkButton,
                QStyle.SP_DialogCancelButton,
                QStyle.SP_DialogApplyButton,
                QStyle.SP_DialogResetButton,
                QStyle.SP_MediaPlay,
                QStyle.SP_MediaStop,
                QStyle.SP_MediaPause,
                QStyle.SP_BrowserReload,
                QStyle.SP_BrowserStop
            ]
            sp = random.choice(candidates)
            icon = self.style().standardIcon(sp)
            if not icon.isNull():
                self.setWindowIcon(icon)
        except Exception as e:
            # 忽略图标设置异常,不中断程序
            pass
    def load_settings(self):
        """加载设置"""
        # 加载代理历史
        proxy_history = self.settings.value("proxy_history", [])
        if proxy_history:
            self.proxy_combo.addItems(proxy_history)
            self.proxy_combo.setCurrentText(proxy_history[0])
        # 加载默认目录
        default_dir = self.settings.value("default_directory", "D:\\clone")
        self.dir_input.setText(default_dir)
        # 加载代理启用状态
        use_proxy = self.settings.value("use_proxy", True, type=bool)
        self.use_proxy_check.setChecked(use_proxy)
    def save_settings(self):
        """保存设置"""
        # 保存代理历史(最多10个)
        proxy_history = []
        for i in range(min(self.proxy_combo.count(), 10)):
            proxy_history.append(self.proxy_combo.itemText(i))
        self.settings.setValue("proxy_history", proxy_history)
        # 保存默认目录
        self.settings.setValue("default_directory", self.dir_input.text())
        # 保存代理启用状态
        self.settings.setValue("use_proxy", self.use_proxy_check.isChecked())
    def save_proxy_to_history(self):
        """保存代理到历史记录"""
        current_proxy = self.proxy_combo.currentText().strip()
        if current_proxy and current_proxy not in [self.proxy_combo.itemText(i) for i in
                                                   range(self.proxy_combo.count())]:
            self.proxy_combo.insertItem(0, current_proxy)
            self.proxy_combo.setCurrentIndex(0)
    def clear_proxy_history(self):
        """清除代理历史"""
        reply = QMessageBox.question(self, "确认", "确定要清除所有代理历史记录吗?",
                                     QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.proxy_combo.clearEditText()
            self.proxy_combo.clear()
            self.settings.remove("proxy_history")
    def insert_example(self, example):
        """插入示例URL"""
        self.url_input.setPlainText(example)
    def browse_directory(self):
        """浏览选择目录"""
        directory = QFileDialog.getExistingDirectory(self, "选择保存目录", self.dir_input.text())
        if directory:
            self.dir_input.setText(directory)
    def set_default_directory(self):
        """设置默认目录"""
        self.settings.setValue("default_directory", self.dir_input.text())
        QMessageBox.information(self, "成功", "已设置为默认目录")
    def open_clone_location(self):
        """打开当前克隆保存位置"""
        path = self.dir_input.text().strip()
        if not path:
            QMessageBox.warning(self, "警告", "未设置保存目录")
            return
        try:
            if not os.path.exists(path):
                os.makedirs(path, exist_ok=True)
        except Exception:
            pass
        QDesktopServices.openUrl(QUrl.fromLocalFile(path))
    def clear_input(self):
        """清空输入"""
        self.url_input.clear()
        self.output_text.clear()
        self.status_label.setText("已清空")
    def start_clone(self):
        """开始执行clone操作"""
        url_input = self.url_input.toPlainText().strip()
        if not url_input:
            QMessageBox.warning(self, "警告", "请输入Git仓库URL")
            return
        target_dir = self.dir_input.text().strip()
        if not target_dir:
            QMessageBox.warning(self, "警告", "请选择保存目录")
            return
        # 清理URL
        if url_input.startswith('git clone '):
            clean_url = url_input[10:].strip()
        else:
            clean_url = url_input.strip()
        # 更新UI状态
        self.clone_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)
        self.progress_bar.setVisible(True)
        self.progress_bar.setRange(0, 0)  # 不确定进度
        self.status_label.setText("正在克隆...")
        # 保存当前代理到历史
        self.save_proxy_to_history()
        # 在新线程中执行clone
        self.clone_thread = CloneThread(
            clean_url,
            target_dir,
            self.use_proxy_check.isChecked(),
            self.proxy_combo.currentText().strip() if self.use_proxy_check.isChecked() else ""
        )
        self.clone_thread.output_signal.connect(self.add_output)
        self.clone_thread.finished_signal.connect(self.clone_finished)
        self.clone_thread.start()
    def stop_clone(self):
        """停止克隆"""
        if self.clone_thread and self.clone_thread.isRunning():
            self.clone_thread.stop()
            self.clone_thread.terminate()
            self.clone_thread.wait()
            self.add_output("\n⏹️ 用户停止操作\n")
            self.clone_finished(False, "用户停止")
    def add_output(self, text):
        """添加输出信息"""
        self.output_text.moveCursor(self.output_text.textCursor().End)
        self.output_text.insertPlainText(text)
        self.output_text.moveCursor(self.output_text.textCursor().End)
    def clone_finished(self, success, message):
        """克隆完成回调"""
        self.clone_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        self.progress_bar.setVisible(False)
        self.status_label.setText(message)
        if success:
            self.clone_btn.setObjectName("success")
            self.clone_btn.style().unpolish(self.clone_btn)
            self.clone_btn.style().polish(self.clone_btn)
        else:
            self.clone_btn.setObjectName("")
            self.clone_btn.style().unpolish(self.clone_btn)
            self.clone_btn.style().polish(self.clone_btn)
    def closeEvent(self, event):
        """关闭事件"""
        if self.clone_thread and self.clone_thread.isRunning():
            reply = QMessageBox.question(self, "确认", "克隆操作仍在进行中,确定要退出吗?",
                                         QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.clone_thread.stop()
                self.clone_thread.terminate()
                self.clone_thread.wait()
                self.save_settings()
                event.accept()
            else:
                event.ignore()
        else:
            self.save_settings()
            event.accept()
def main():
    app = QApplication(sys.argv)
    # 设置应用程序属性
    app.setApplicationName("Git Clone Tool")
    app.setApplicationVersion("1.0")
    app.setOrganizationName("GitCloneTool")
    window = GitCloneGUI()
    window.show()
    sys.exit(app.exec_())
if __name__ == "__main__":
    main()

目录, 按钮

kongjkd   

人生苦短 我用Python  加油
feiyang2024   

Python 学习一下 加油
zkai529   

相当实用嗷
snakegao   

向楼主 学习一下 感谢
您需要登录后才可以回帖 登录 | 立即注册

返回顶部