分类: Python

Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。

Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。

像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。

官方宣布,2020 年 1 月 1 日, 停止 Python 2 的更新。

Python 2.7 被确定为最后一个 Python 2.x 版本。

  • python 桌面时间

    代码来源:

    https://mp.weixin.qq.com/s/kuyObP50ZfsbZ9IKqp_IDw

    from tkinter import *
    import time, datetime
    from time import gmtime, strftime
    
    root =Tk()
    
    # Window Attributes
    root.overrideredirect(1)# 隐藏窗口边框
    root.wm_attributes("-transparentcolor","gray99")# 设置透明背景色
    
    running =True# 运行状态
    
    # 关闭窗口函数
    def close(event):
        global running
        running = False
    
    root.bind('<Escape>', close)# 绑定Esc键关闭窗口
    
    screen_width = root.winfo_screenwidth()# 获取屏幕宽度
    screen_height = root.winfo_screenheight()# 获取屏幕高度
    
    timeframe =Frame(root, width=screen_width, height=screen_height, bg="gray99")# 创建主框架
    timeframe.grid(row=0,column=0)
    
    tkintertime =StringVar()# 创建时间变量
    timelabel =Label(timeframe, textvariable=tkintertime, fg="white", bg="gray99", font=("NovaMono",40))# 创建时间标签
    timelabel.place(y=screen_height/2-60, x=screen_width/2, anchor="center")# 设置时间标签位置
    
    tkinterdate =StringVar()# 创建日期变量
    datelabel =Label(timeframe, textvariable=tkinterdate, fg="white", bg="gray99", font=("Bahnschrift",15))# 创建日期标签
    datelabel.place(y=screen_height/2+60, x=screen_width/2, anchor="center")# 设置日期标签位置
    
    while running:
        tkintertime.set(value=strftime("%H:%M:%S"))# 更新时间
        tkinterdate.set(value=strftime("%A, %d %B"))# 更新日期
        root.update_idletasks()# 更新窗口
        root.update()# 更新窗口
        time.sleep(1)  # 延迟1秒

     

  • win清理python残余

    rd /s/q %USERPROFILE%\AppData\Local\Python
    rd /s/q %USERPROFILE%\AppData\Local\pip
    reg delete “HKCU\Software\Python” /f
    rd /s/q %USERPROFILE%\AppData\Roaming\Python
    rd /s/q %USERPROFILE%\AppData\Roaming\pip

    rd /s/q “C:\Users\%USERNAME%\.ipython”

    rd /s/q “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Python 3.8”

    rd /s/q “C:\Users\Public\Documents\Python Scripts”

    rd /s/q “C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.8”

    rd /s/q “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Python 3.8”

    rd /s/q “C:\Users\rkey\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.5”

    rd /s/q “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Python 3.12”

  • flask创建一个database.py,里面只用来创建db,models文件夹下的post.py导入db,app里创建数据库表

    也算是一个避免循环导入的例子吧.

    来源:文心一言,但是我稍有修改.

    在 Flask 项目中,你可以通过以下步骤来组织代码,以便在 database.py 文件中创建数据库连接,并在 models/post.py 文件中定义模型,然后在 Flask 应用中创建数据库表。

    项目结构
    假设你的项目结构如下:

    my_flask_app/
    │
    ├── app.py
    ├── database.py
    ├── models/
    │ └── post.py
    └── ...

    1. 创建 database.py
    在 database.py 文件中,我们将创建一个 SQLAlchemy 数据库实例。
    # database.py

    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()

    2. 创建 models/post.py
    在 models/post.py 文件中,我们将导入 database.py 中的 db 实例,并定义一个 Post 模型。
    # models/post.py

    from database import db
    from datetime import datetime
    
    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(100), nullable=False)
        content = db.Column(db.Text, nullable=False)
        date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    
    def __repr__(self):
        return f"Post('{self.title}', '{self.date_posted}')"

    3. 在 app.py 中配置 Flask 应用和数据库
    在 app.py 文件中,我们将配置 Flask 应用,创建数据库连接,并应用迁移来创建数据库表。
    # app.py

    from flask import Flask 
    from flask_sqlalchemy import SQLAlchemy 
    from database import db 
    from models.post import Post 
    app = Flask(__name__)
    
    # 配置数据库 URI
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' # 你可以使用其他数据库,比如 MySQL, PostgreSQL 等
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    # 初始化数据库实例
    db.init_app(app)
    
    @app.route('/')
    def home():
        posts = Post.query.all()
        return f"Home Page<br>{[post.title for post in posts]}"
    
    if __name__ == '__main__':
        # 创建所有表
        with app.app_context():
            db.create_all()
    
        # 运行 Flask 应用
        app.run(debug=True)

    cmd命令提示符里运行以下命令:

    python app.py

    现在,你的 Flask 应用应该能够启动,并且会在 site.db 中创建 post 表。访问 http://127.0.0.1:5000/ 将显示主页,尽管目前还没有任何帖子。

    这样,你就成功地创建了一个 Flask 项目,其中包含数据库连接、模型定义和数据库表创建逻辑。

  • root.wm_iconbitmap()和root.iconbitmap()两个函数有啥区别

    在Tkinter中,root.wm_iconbitmap()root.iconbitmap() 都是用来设置窗口图标的方法,但它们之间存在一些差异:

    1. root.iconbitmap()
      • 这个方法是Tkinter提供的一个接口,用于设置窗口的图标。
      • 它只能加载.ico格式的图标文件,不支持其他格式如.png.jpg
      • 使用方法简单,只需要提供图标文件的路径即可:
        root.iconbitmap("/path/to/your/icon.ico")
    2. root.wm_iconbitmap()
      • 这个方法实际上是root.wm()方法的一个子命令,wm是Tkinter窗口方法(Window Manager)的缩写,用于与窗口管理器进行交互。
      • 它同样用于设置窗口图标,但调用方式与iconbitmap()不同,它需要通过wm方法来调用iconbitmap命令。
      • 使用wm_iconbitmap()时,你需要传递窗口实例和图标文件路径:
        root.wm_iconbitmap("/path/to/your/icon.ico")
      • 这个方法在功能上与iconbitmap()相似,但调用方式更为底层,因为它直接通过Tkinter的wm子系统与窗口管理器通信

    总结来说,root.iconbitmap()root.wm_iconbitmap()都可以设置窗口图标,但iconbitmap()是Tkinter提供的更高层的接口,而wm_iconbitmap()则通过wm子系统提供了一种更为底层的调用方式。在实际使用中,两者的效果相同,但iconbitmap()因其简单易用而更常被使用。

  • pip install -U这个参数-U是啥意思

    pip install -U 命令中的 -U 参数是用于更新指定的包到最新版本。这里的 -U--upgrade 的缩写。当你使用这个参数时,pip 会检查指定包的最新版本,并将其更新到最新版本,如果该包已经是最新版,则不会有任何变化。

    例如,如果你想要更新 requests 包,你可以使用以下命令:

    pip install -U requests

    这会将 requests 包更新到最新版本。如果你没有指定包名,pip install -U 会尝试更新所有已安装的包。

  • python库Nuitka-2.4.11依赖

    nuitka-2.4.11

     

    ordered-set-4.1.0

    zstandard-0.21.0

     


    Collecting nuitka
    Downloading Nuitka-2.4.11.tar.gz (3.7 MB)
    —————————————- 3.7/3.7 MB 1.4 MB/s eta 0:00:00
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Preparing metadata (pyproject.toml) … done
    Collecting ordered-set>=4.1.0 (from nuitka)
    Downloading ordered_set-4.1.0-py3-none-any.whl.metadata (5.3 kB)
    Collecting zstandard>=0.15 (from nuitka)
    Downloading zstandard-0.21.0-cp37-cp37m-win_amd64.whl.metadata (3.0 kB)
    Downloading ordered_set-4.1.0-py3-none-any.whl (7.6 kB)
    Downloading zstandard-0.21.0-cp37-cp37m-win_amd64.whl (659 kB)
    —————————————- 659.7/659.7 kB 6.0 MB/s eta 0:00:00
    Building wheels for collected packages: nuitka
    Building wheel for nuitka (pyproject.toml) … done
    Created wheel for nuitka: filename=Nuitka-2.4.11-cp37-cp37m-win_amd64.whl size=3402958 sha256=aa8e430bd06ad97a6d2eb25fc9e19b7915d2d5b14a0e401245907b8895952af7
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\8c\89\72\e408cd495b3903ecbad851052183da7c128679edba64c98f50
    Successfully built nuitka
    Installing collected packages: zstandard, ordered-set, nuitka
    Successfully installed nuitka-2.4.11 ordered-set-4.1.0 zstandard-0.21.0

  • flask-bt之tracker录入

    templates\trackers_index.html

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>trackers</title>
    </head>
    <body>
        {% if session.logged_in %}
        <form action="/logout" method="get">
            <input type="submit" value="登出">
        </form>
        {% else %}
        <form action="/login" method="post">
            <input type="text" name="username" placeholder="用户名">
            <input type="password" name="password" id="password" placeholder="密码">
            <input type="submit" value="登录">
        </form>
        {% endif %}
        <main>
            <!-- flask的flash函数专用固定代码 专门用来显示内容的 -->
            {% for message in get_flashed_messages() %}         
                <div class="alert">{{ message }}</div>     
            {% endfor %}
        </main>
        <p>tracker总数量:{{count}}</p>
        <form action="/trackers_search" method="post">
            <input type="text" name="trackers_name" placeholder="请输入tracker关键字">
            <input type="submit" value="搜索">
        </form>
        {% if session.logged_in %}
        <!-- 登录表单,实际上用户已经登录,所以可以显示欢迎信息或其他内容 -->
        <form action="/trackers_add" method="post">
            <label for="trackers_name">trackers_add:</label>
            <input type="text" name="trackers_name" placeholder="请输入完整的tracker链接">
            <input type="submit" value="提交">
        </form>
        <form action="/trackers_delete" method="post">
            <label for="trackers_name">trackers_delete:</label>
            <input type="text" name="trackers_name" placeholder="请输入完整的tracker链接">
            <input type="submit" value="删除">
        </form>
        {% endif %}
    
        <hr>
        <div class="tracker_box scrollable-div">
            <form action="/get_trackers_as_text" method="get">
                <input type="submit" value="去复制,请使用Ctrl+A和Ctrl+C复制">
            </form>
            {% for i in trackers %}
            <ul style="list-style-type: none">
                <li>{{i.name}}</li>
            </ul>
            {% endfor %}
        </div>
    </body>
    </html>
    <style>
        * {
            margin:0;
            padding:0;
        }
        .scrollable-div {
            height: 800px; /* 或者你需要的高度 */
            overflow-y: auto; /* 内容超出时在 y 轴方向显示滚动条 */
            overflow-x: auto; /* 内容超出时在 x 轴方向显示滚动条 */
        }
    </style>

     

    app.py

    from flask import Flask, request, render_template, redirect, url_for, flash, session
    from flask_sqlalchemy import SQLAlchemy
    import os
    from datetime import datetime
    from flask_cors import CORS
    import secrets
    '''
    待实现:
    flash错误提示显示红色,警告信息显示黄色,成功显示绿色,使用div画出来
    '''
    
    app = Flask(__name__)
    # 为整个应用启用 CORS
    CORS(app)
    # 启用 CORS 并设置特定的域名
    #CORS(app, resources={r"/some_route": {"origins": "http://example.com"}})
    
    # 或者,允许所有域名访问所有路由
    CORS(app, resources={r"*": {"origins": "*"}})
    
    # 获取当前文件的路径
    basedir = os.path.abspath(os.path.dirname(__file__))
    # 设置数据库文件的路径为当前目录下的 data.db
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.db')
    #app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////data.db'
    
    app.secret_key = secrets.token_urlsafe()  # 用于保持会话安全,字符串随机即可
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False#模型修改的跟踪
    db = SQLAlchemy(app)
    
    class Trackers(db.Model):
       __tablename__= 'trackers'
       id = db.Column(db.Integer, unique=True, comment='id')
       name = db.Column(db.String(64), primary_key=True, comment='Trackers,主键')
       is_usable = db.Column(db.String(64), unique=False, comment='Tracker是否可用')
       create_date = db.Column(db.DateTime, unique=False, default=datetime.now(), comment='Tracker创建日期')
       update_date = db.Column(db.DateTime, unique=False, comment='Tracker更新日期')
       def __repr__(self):
          return '<Trackers %r>' % self.name
    
    def create_tables():
        with app.app_context():
            db.create_all()
    
    
    @app.route('/')
    @app.route('/trackers_index')
    def trackers_index():
        trackers = Trackers.query.order_by(Trackers.create_date.desc()).all()#倒序输出所有
        count = Trackers.query.count()#tracker总数量
        return render_template('trackers_index.html', trackers=trackers, count=count)
    
    
    @app.route('/get_trackers_as_text')
    def get_trackers_as_text():
        trackers = Trackers.query.all()
        lines = [f"{tracker.name}" for tracker in trackers]
        text = "<br>".join(lines)
        return text
    
    
    @app.route('/trackers_add', methods=['POST'], endpoint='add_announcement')
    def announcement_add():
        trackers_name = request.form['trackers_name']
        # 关键词列表
        keywords = ['announce', 'http', 'udp', 'https', 'wss']
        # 检查字符串是否包含列表中的任意关键词
        if contains_keywords(trackers_name, keywords) or trackers_name.endswith('announce'):
            print("提交信息中包含关键字")
        else:
            flash("你提交的可能不是tracker链接")
            return redirect(url_for('trackers_index'))
        exists = Trackers.query.filter_by(name=trackers_name).first() is not None
        if exists:
            flash('tracker 已经存在.')
        else:
            flash('tracker 不存在,已插入.')
            new_tracker = Trackers(name=trackers_name)
            db.session.add(new_tracker)
            db.session.commit()
        return redirect(url_for('trackers_index'))
    
    def contains_keywords(s, keywords):
        return any(keyword in s for keyword in keywords)
    
    @app.route('/trackers_delete/<int:trackers_name>', methods=['POST'], endpoint='delete_announcement_specific')
    def delete_announcement_specific(trackers_name):
        data = Trackers.query.filter_by(name=trackers_name).first()
        if data:
            db.session.delete(data)
            db.session.commit()
            flash(f'【{data}】已删除')
            return redirect(url_for('trackers_index'))
        else:
            return 'Tracker not found'
    
    @app.route('/trackers_delete', methods=['POST'], endpoint='delete_announcement')
    def delete_announcement():
        trackers_name = request.form.get('trackers_name') or request.view_args.get('trackers_name')
        if not trackers_name:
            return '什么都没输入,你删除啥呢!!!'
        data = Trackers.query.filter_by(name=trackers_name).first()
        if data:
            db.session.delete(data)
            db.session.commit()
            flash(f'{data}已删除')
            return redirect(url_for('trackers_index'))
        else:
            return f'数据库中不存在该数据!!!{trackers_name}'
        
    
    @app.route('/trackers_update/<int:trackers_name>', methods=['POST'], endpoint='update_announcement')
    def announcement_update(trackers_name):
        data = Trackers.query.filter_by(name=trackers_name).first()
        if data:
            data.name = request.form.get('name')
            data.is_usable = request.form.get('description')
            db.session.commit()
            flash('Data has been updated successfully.', 'success')
        else:
            flash('Data not found.', 'error')
        return redirect(url_for('trackers_index'))
    
    
    @app.route('/trackers_search', methods=['GET', 'POST'])
    def announcement_search():
        if request.method == 'POST':
            trackers_name = request.form.get('trackers_name')
            trackers = Trackers.query.filter(Trackers.name.like(f'%{trackers_name}%')).all()
            return render_template('trackers_index.html', trackers=trackers)
        return render_template('trackers_index.html')
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            username = request.form['username']
            password = request.form['password']
            if username == 'admin' and password == 'admin':
                session['logged_in'] = True
                session['username'] = username
                flash("登陆成功")
                return redirect(url_for('trackers_index'))
            else:
                return '无效的用户名或密码'
        return redirect(url_for('trackers_index'))
    
    
    @app.route('/logout', methods=['GET', 'POST'])
    def logout():
        session.pop('logged_in', None)
        session.pop('username', None)
        return redirect(url_for('trackers_index'))
    
    
    if __name__ == '__main__':
        # 创建数据库
        create_tables()
        app.run(debug=True, host='0.0.0.0', port=5000)

     

  • .pyc文件对程序性能提升有多大?

    .pyc 文件对程序性能的提升主要体现在以下几个方面:

    1. 加快程序加载速度.pyc 文件是预编译的字节码,Python 解释器可以直接加载它,避免了每次运行时重新编译源代码的过程。这可以减少程序的启动时间,特别是在大型项目中,如果有大量的 .py 文件,使用 .pyc 文件可以显著减少程序启动时间
    2. 减少解释器的编译负担:使用 .pyc 文件可以减轻 Python 解释器的编译负担,因为不需要每次都对 .py 文件进行编译
    3. 提高运行效率.pyc 文件是一个可执行的字节码文件,目的是节省 Python 解析器翻译时间,从而提高运行效率。虽然性能提升可能只是一点点,但对于大型项目来说,节省的时间会更多一些
    4. 保护源代码:发布程序时,只提供 .pyc 文件可以有效隐藏源代码,防止他人查看或修改,这在一定程度上也减少了代码被篡改的风险,从而可能间接提高程序的稳定性和安全性

    总的来说,.pyc 文件对程序性能的提升主要体现在加快程序加载速度和减少解释器编译负担上,对于大型项目或者频繁启动的程序,这种性能提升会更加明显。然而,对于单次执行的小型脚本,这种性能提升可能不太显著。

  • .pyc是啥文件?如何执行.pyc文件

    .pyc 文件是 Python 程序的编译文件,它是 Python 源代码(.py 文件)的字节码版本。.pyc 文件通常由 Python 解释器在需要时自动生成,用于提高程序的加载速度,因为从 .pyc 文件加载代码比从 .py 文件编译代码要快。

    执行 .pyc 文件的方法如下:

    1. 直接执行.pyc 文件可以直接被 Python 解释器执行。你只需要在命令行中使用 Python 解释器,然后指定 .pyc 文件的路径即可。例如:
      python your_script.pyc

      或者如果你使用的是 Python 3.x 版本,可能需要使用:

      python3 your_script.pyc
    2. 使用 import 语句: 你也可以在 Python 程序中使用 import 语句来导入 .pyc 文件,就像导入普通的 .py 文件一样。例如:
      import your_script
    3. 使用 exec 函数: 如果你有一个 .pyc 文件的路径,可以使用 exec 函数来执行其中的代码。例如:
      with open('your_script.pyc', 'rb') as file:
          exec(file.read())

    请注意,.pyc 文件是针对特定版本的 Python 解释器生成的,这意味着它们可能不兼容不同版本的 Python。此外,出于安全考虑,.pyc 文件不应该从不可信任的来源执行,因为它们可能包含恶意代码。

  • python创建一个隐藏的后台进程,用于执行指定更换WIn10桌面背景图片的脚本

    任务管理器是看不到的,使用Process Explorer可以查看到这个进程。

    要使用ShellExecuteEx来启动进程,你需要从shell32库导入这个函数,并定义相应的结构体和参数。以下是如何在你的代码中使用ShellExecuteEx来替代CreateProcess的示例:

    首先,你需要定义SHELLEXECUTEINFO结构体,并设置适当的参数。然后,使用ShellExecuteEx函数来启动进程。

    步骤1: 定义SHELLEXECUTEINFO结构体

    import ctypes
    from ctypes import wintypes
    from ctypes.wintypes import DWORD, HANDLE, BOOL, WORD
    
    # 定义 SECURITY_ATTRIBUTES 结构体
    class SECURITY_ATTRIBUTES(ctypes.Structure):
        _fields_ = [
            ("nLength", wintypes.DWORD),
            ("lpSecurityDescriptor", wintypes.LPVOID),
            ("bInheritHandle", wintypes.BOOL),
        ]
    
    # 定义 SHELLEXECUTEINFO 结构体
    class SHELLEXECUTEINFO(ctypes.Structure):
        _fields_ = [
            ("cbSize", wintypes.UINT),
            ("fMask", wintypes.UINT),
            ("hwnd", wintypes.HWND),
            ("lpVerb", wintypes.LPCWSTR),
            ("lpFile", wintypes.LPCWSTR),
            ("lpParameters", wintypes.LPCWSTR),
            ("lpDirectory", wintypes.LPCWSTR),
            ("nShow", wintypes.INT),
            ("hInstApp", wintypes.HINSTANCE),
            ("lpIDList", wintypes.LPVOID),
            ("lpClass", wintypes.LPCWSTR),
            ("hkeyClass", wintypes.HKEY),
            ("dwHotKey", wintypes.DWORD),
            ("hIcon", wintypes.HANDLE),
            ("hProcess", wintypes.HANDLE),
        ]

    步骤2: 加载shell32库并定义ShellExecuteEx函数

    # 加载 shell32 库
    shell32 = ctypes.WinDLL('shell32', use_last_error=True)
    
    # 定义 ShellExecuteEx 函数
    ShellExecuteEx = shell32.ShellExecuteExW
    ShellExecuteEx.argtypes = [
        ctypes.POINTER(SHELLEXECUTEINFO),
    ]
    ShellExecuteEx.restype = wintypes.BOOL

    步骤3: 准备参数并调用ShellExecuteEx

    # 设置命令和参数
    src = r"C:\Users\rkey\Desktop\测试\更换桌面壁纸\change_wallpaper.py"
    command = f"cmd.exe /c python {src}"
    
    # 初始化 SHELLEXECUTEINFO 结构体
    sei = SHELLEXECUTEINFO()
    sei.cbSize = ctypes.sizeof(SHELLEXECUTEINFO)
    sei.fMask = 0x00000040  # SEE_MASK_NOCLOSEPROCESS
    sei.hwnd = None
    sei.lpVerb = None  # 不使用动词
    sei.lpFile = "cmd.exe"
    sei.lpParameters = f"/c {command}"
    sei.lpDirectory = None
    sei.nShow = 0  # SW_HIDE
    sei.hInstApp = 0
    
    # 调用 ShellExecuteEx
    if ShellExecuteEx(ctypes.byref(sei)):
        print("Process created successfully.")
    else:
        print("Failed to create process. Error code:", ctypes.get_last_error())
    
    # 等待进程结束
    # kernel32.WaitForSingleObject(sei.hProcess, -1)
    # 关闭进程句柄
    # kernel32.CloseHandle(sei.hProcess)

     

    注意事项
    错误处理:添加错误处理代码,以便在命令执行失败时获取更多信息。
    进程句柄:ShellExecuteEx函数执行后,sei.hProcess将包含新创建的进程的句柄。你可以使用这个句柄来等待进程结束或关闭句柄。
    这样,你就可以使用ShellExecuteEx来启动一个后台进程,而不会挂起。

     

    完整代码:

    import ctypes
    from ctypes import wintypes
    from ctypes.wintypes import DWORD, HANDLE, BOOL, WORD
    
    # 定义 SHELLEXECUTEINFO 结构体
    class SHELLEXECUTEINFO(ctypes.Structure):
        _fields_ = [
            ("cbSize", wintypes.UINT),
            ("fMask", wintypes.UINT),
            ("hwnd", wintypes.HWND),
            ("lpVerb", wintypes.LPCWSTR),
            ("lpFile", wintypes.LPCWSTR),
            ("lpParameters", wintypes.LPCWSTR),
            ("lpDirectory", wintypes.LPCWSTR),
            ("nShow", wintypes.INT),
            ("hInstApp", wintypes.HINSTANCE),
            ("lpIDList", wintypes.LPVOID),
            ("lpClass", wintypes.LPCWSTR),
            ("hkeyClass", wintypes.HKEY),
            ("dwHotKey", wintypes.DWORD),
            ("hIcon", wintypes.HANDLE),
            ("hProcess", wintypes.HANDLE),
        ]
    
    # 加载 shell32 库
    shell32 = ctypes.WinDLL('shell32', use_last_error=True)
    
    # 定义 ShellExecuteEx 函数
    ShellExecuteEx = shell32.ShellExecuteExW
    ShellExecuteEx.argtypes = [
        ctypes.POINTER(SHELLEXECUTEINFO),
    ]
    ShellExecuteEx.restype = wintypes.BOOL
    
    # 设置命令和参数
    src = r"C:\Users\rkey\Desktop\测试\更换桌面壁纸\change_wallpaper.py"
    command = f"cmd.exe /c python {src}"
    
    # 初始化 SHELLEXECUTEINFO 结构体
    sei = SHELLEXECUTEINFO()
    sei.cbSize = ctypes.sizeof(SHELLEXECUTEINFO)
    sei.fMask = 0x00000040  # SEE_MASK_NOCLOSEPROCESS
    sei.hwnd = None
    sei.lpVerb = None  # 不使用动词
    sei.lpFile = "cmd.exe"
    sei.lpParameters = f"/c {command}"
    sei.lpDirectory = None
    sei.nShow = 0  # SW_HIDE
    sei.hInstApp = 0
    
    # 调用 ShellExecuteEx
    if ShellExecuteEx(ctypes.byref(sei)):
        print("Process created successfully.")
    else:
        print("Failed to create process. Error code:", ctypes.get_last_error())
    
    # 等待进程结束
    # kernel32.WaitForSingleObject(sei.hProcess, -1)
    # 关闭进程句柄
    # kernel32.CloseHandle(sei.hProcess)