分类: 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打印多个当前安装的模块的版本

    modules = ["pywin32", "pandas", "matplotlib"]  # 替换为你要检查的模块名
    
    for module_name in modules:
        try:
            version = pkg_resources.get_distribution(module_name).version
            print(f"{module_name} version: {version}")
        except pkg_resources.DistributionNotFound:
            print(f"{module_name} is not installed.")

     

  • python指定一个文件夹的图片每10秒替换一次桌面图片

    pywin32库版本308

    import os
    import time
    import win32con
    import win32gui
    
    def set_wallpaper(image_path):
        # 设置桌面壁纸
        win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, image_path, win32con.SPIF_UPDATEINIFILE | win32con.SPIF_SENDCHANGE)
    
    def change_wallpaper_every_10_seconds(folder_path):
        # 获取文件夹中所有图片文件的路径
        image_files = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.endswith(('.jpg', '.jpeg', '.png', '.bmp'))]
        if not image_files:
            print("No image files found in the folder.")
            return
    
        # 循环更换壁纸
        while True:
            for image_file in image_files:
                set_wallpaper(image_file)
                print(f"Wallpaper changed to: {image_file}")
                time.sleep(10)  # 等待10秒
    
    # 设置图片文件夹路径
    folder_path = r"C:\Users\rkey\Pictures\Screenshots"  # 替换为你的图片文件夹路径
    change_wallpaper_every_10_seconds(folder_path)

     

  • tkinter学习

    root.attributes('-topmost', True):这行代码将窗口设置为始终置顶。

    root.overrideredirect(True):这行代码隐藏窗口边框。

  • python项目-trackerlist数据库

    因为要网上一个个查询bt种子的tacker列表,所以我自己弄了一个用来存储tracker的工具。

    默认用户名:admin,密码:admin,没有存在数据库中,改成自己需要的即可

    增删查都写好了,不需要改什么。信息不是太多,直接删除不需要的tracker链接,重新添加即可

    用的sqlite数据库,需要移动项目的时候直接把文件夹复制走即可

     

    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)

     

  • flask跨域

    跨域资源共享(CORS)是一种安全机制,它允许或限制网页上哪些域名可以访问资源。在 Flask 应用中,你可以使用 Flask-CORS 扩展来处理跨域请求。

    以下是如何在 Flask 应用中启用 CORS 的步骤:

    安装 Flask-CORS

    首先,你需要安装 Flask-CORS:

    pip install flask-cors

    启用 CORS

    然后,在你的 Flask 应用中启用 CORS。你可以为整个应用或特定的路由启用 CORS。

    from flask import Flask
    from flask_cors import CORS
    
    app = Flask(__name__)
    
    # 为整个应用启用 CORS
    CORS(app)
    
    # 或者,只为特定的路由启用 CORS
    @app.route('/some_route')
    def some_route():
        # 你的处理逻辑
        pass
    
    # 启用 CORS 并设置特定的域名
    CORS(app, resources={r"/some_route": {"origins": "http://example.com"}})
    
    # 或者,允许所有域名访问所有路由
    CORS(app, resources={r"*": {"origins": "*"}})

    设置 CORS 选项

    你可以设置不同的选项来控制 CORS 的行为,例如允许的头部、方法和最大年龄。

    CORS(app, resources={r"/api/*": {
        "origins": "http://example.com",
        "methods": ["GET", "POST", "PUT", "DELETE"],
        "allow_headers": ["Content-Type", "Authorization"],
        "max_age": 21600
    }})

    处理 OPTIONS 请求

    CORS 预检请求(OPTIONS 请求)通常用于检查实际请求是否安全。Flask-CORS 会自动处理 OPTIONS 请求,所以你不需要手动编写处理逻辑。

    注意事项

    • 确保你了解 CORS 的安全含义,不要在生产环境中过于宽松地设置 CORS 策略。
    • 如果你的应用需要处理敏感数据,考虑使用 HTTPS 来保护数据传输的安全。
    • 在开发环境中,一些浏览器插件可能会自动添加 CORS 头部,这可能会干扰你的跨域请求测试。

    通过使用 Flask-CORS,你可以轻松地管理 Flask 应用中的跨域请求,确保应用的安全性和灵活性。

  • flask_sqlalchemy

    模型字段

    db.Integer

    db.String(64)

    db.Date
    db.DateTime
    查询
    模型名.query.count()#数据库表的总条目数量
    模型名.query.order_by(模型名.create_date.desc()).all()#倒序输出所有数据
  • app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘sqlite:////data.db’创建在当前目录下

    在 Flask 应用中,当你设置 SQLALCHEMY_DATABASE_URI 配置项为 'sqlite:////data.db' 时,你告诉 SQLAlchemy 使用 SQLite 数据库,并且数据库文件名为 data.db。SQLite 的数据库是一个单一的文件,因此你不需要像其他数据库那样设置主机名、用户名或密码。

    'sqlite:////data.db' 中的四个斜杠意味着:

    • 第一个和第二个斜杠:指定数据库类型为 SQLite。
    • 第三个和第四个斜杠:指定数据库文件的路径。在这里,路径是相对于 Flask 应用的当前工作目录。

    如果你想要确保数据库文件创建在 Flask 应用的当前目录下,你可以使用以下配置:

    import os
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    # 使用 url_for 时需要设置静态文件夹
    app.config['STATIC_FOLDER'] = 'static'
    
    # 获取当前文件的路径
    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_TRACK_MODIFICATIONS'] = False
    
    db = SQLAlchemy(app)
    
    # 确保在应用上下文中创建数据库
    with app.app_context():
        db.create_all()
    
    # 其余的代码...

    在这个示例中,我们使用 os.path.abspathos.path.dirname 来获取当前文件(通常是你的 Flask 应用的主模块文件)的绝对路径,然后使用 os.path.join 来构建数据库文件的完整路径。这样,无论应用在哪里运行,数据库文件 data.db 都会被创建在应用的当前目录下。

    请注意,app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 这一行是用来关闭 SQLAlchemy 的修改跟踪,这可以避免在生产环境中记录不必要的信息,从而提高性能。

  • python库flask_sqlalchemy-3.0.5依赖

    flask_sqlalchemy-3.0.5

     

    flask-2.2.5

    flask-sqlalchemy-3.0.5

    sqlalchemy-2.0.36


    Collecting flask-sqlalchemy
    Downloading flask_sqlalchemy-3.0.5-py3-none-any.whl.metadata (3.3 kB)
    Collecting flask>=2.2.5 (from flask-sqlalchemy)
    Downloading Flask-2.2.5-py3-none-any.whl.metadata (3.9 kB)
    Collecting sqlalchemy>=1.4.18 (from flask-sqlalchemy)
    Downloading SQLAlchemy-2.0.36-cp37-cp37m-win_amd64.whl.metadata (9.9 kB)
    Requirement already satisfied: Werkzeug>=2.2.2 in c:\program files\python37\lib\site-packages (from flask>=2.2.5->flask-sqlalchemy) (2.2.3)
    Requirement already satisfied: Jinja2>=3.0 in c:\program files\python37\lib\site-packages (from flask>=2.2.5->flask-sqlalchemy) (3.1.4)
    Requirement already satisfied: itsdangerous>=2.0 in c:\program files\python37\lib\site-packages (from flask>=2.2.5->flask-sqlalchemy) (2.1.2)
    Requirement already satisfied: click>=8.0 in c:\program files\python37\lib\site-packages (from flask>=2.2.5->flask-sqlalchemy) (8.1.7)
    Requirement already satisfied: importlib-metadata>=3.6.0 in c:\program files\python37\lib\site-packages (from flask>=2.2.5->flask-sqlalchemy) (6.7.0)
    Requirement already satisfied: typing-extensions>=4.6.0 in c:\program files\python37\lib\site-packages (from sqlalchemy>=1.4.18->flask-sqlalchemy) (4.7.1)
    Requirement already satisfied: greenlet!=0.4.17 in c:\program files\python37\lib\site-packages (from sqlalchemy>=1.4.18->flask-sqlalchemy) (3.1.1)
    Requirement already satisfied: colorama in c:\program files\python37\lib\site-packages (from click>=8.0->flask>=2.2.5->flask-sqlalchemy) (0.4.6)
    Requirement already satisfied: zipp>=0.5 in c:\program files\python37\lib\site-packages (from importlib-metadata>=3.6.0->flask>=2.2.5->flask-sqlalchemy) (3.15.0)
    Requirement already satisfied: MarkupSafe>=2.0 in c:\program files\python37\lib\site-packages (from Jinja2>=3.0->flask>=2.2.5->flask-sqlalchemy) (2.1.5)
    Downloading flask_sqlalchemy-3.0.5-py3-none-any.whl (24 kB)
    Downloading Flask-2.2.5-py3-none-any.whl (101 kB)
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 101.8/101.8 kB 279.2 kB/s eta 0:00:00
    Downloading SQLAlchemy-2.0.36-cp37-cp37m-win_amd64.whl (2.1 MB)
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 1.8 MB/s eta 0:00:00
    Installing collected packages: sqlalchemy, flask, flask-sqlalchemy
    Attempting uninstall: flask
    Found existing installation: Flask 2.2.3
    Uninstalling Flask-2.2.3:
    Successfully uninstalled Flask-2.2.3
    Successfully installed flask-2.2.5 flask-sqlalchemy-3.0.5 sqlalchemy-2.0.36

  • python库flask-3.0.3依赖

    flask-3.0.3

     

    Jinja2-3.1.4

    MarkupSafe-2.1.5

    Werkzeug-3.0.5

    blinker-1.8.2

    click-8.1.7

    colorama-0.4.6

    flask-3.0.3

    importlib-metadata-8.5.0

    itsdangerous-2.2.0 zipp-3.20.2

     


    Collecting flask
    Downloading flask-3.0.3-py3-none-any.whl (101 kB)
    |████████████████████████████████| 101 kB 125 kB/s
    Collecting blinker>=1.6.2
    Downloading blinker-1.8.2-py3-none-any.whl (9.5 kB)
    Collecting Jinja2>=3.1.2
    Downloading jinja2-3.1.4-py3-none-any.whl (133 kB)
    |████████████████████████████████| 133 kB 145 kB/s
    Collecting itsdangerous>=2.1.2
    Downloading itsdangerous-2.2.0-py3-none-any.whl (16 kB)
    Collecting importlib-metadata>=3.6.0; python_version < “3.10”
    Downloading importlib_metadata-8.5.0-py3-none-any.whl (26 kB)
    Collecting click>=8.1.3
    Downloading click-8.1.7-py3-none-any.whl (97 kB)
    |████████████████████████████████| 97 kB 97 kB/s
    Collecting Werkzeug>=3.0.0
    Downloading werkzeug-3.0.5-py3-none-any.whl (227 kB)
    |████████████████████████████████| 227 kB 56 kB/s
    Collecting MarkupSafe>=2.0
    Downloading MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl (17 kB)
    Collecting zipp>=3.20
    Downloading zipp-3.20.2-py3-none-any.whl (9.2 kB)
    Collecting colorama; platform_system == “Windows”
    Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB)
    Installing collected packages: blinker, MarkupSafe, Jinja2, itsdangerous, zipp, importlib-metadata, colorama, click, Werkzeug, flask
    Successfully installed Jinja2-3.1.4 MarkupSafe-2.1.5 Werkzeug-3.0.5 blinker-1.8.2 click-8.1.7 colorama-0.4.6 flask-3.0.3 importlib-metadata-8.5.0 itsdangerous-2.2.0 zipp-3.20.2
    WARNING: You are using pip version 20.1.1; however, version 24.2 is available.
    You should consider upgrading via the ‘c:\application\python\python385\python.exe -m pip install –upgrade pip’ command.

  • python库PyAutoGUI-0.9.54依赖

    PyAutoGUI-0.9.54

     

    Pillow-9.5.0

    mouseinfo-0.1.3

    pyautogui-0.9.54

    pygetwindow-0.0.9

    pymsgbox-1.0.9

    pyperclip-1.9.0

    pyrect-0.2.0

    pyscreeze-1.0.1

    pytweening-1.2.0

     


    Collecting pyautogui
    Downloading PyAutoGUI-0.9.54.tar.gz (61 kB)
    —————————————- 61.2/61.2 kB 232.9 kB/s eta 0:00:00
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting pymsgbox (from pyautogui)
    Downloading PyMsgBox-1.0.9.tar.gz (18 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting pytweening>=1.0.4 (from pyautogui)
    Downloading pytweening-1.2.0.tar.gz (171 kB)
    —————————————- 171.2/171.2 kB 644.0 kB/s eta 0:00:00
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting pyscreeze>=0.1.21 (from pyautogui)
    Downloading pyscreeze-1.0.1.tar.gz (27 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Preparing metadata (pyproject.toml) … done
    Collecting pygetwindow>=0.0.5 (from pyautogui)
    Downloading PyGetWindow-0.0.9.tar.gz (9.7 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting mouseinfo (from pyautogui)
    Downloading MouseInfo-0.1.3.tar.gz (10 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting pyrect (from pygetwindow>=0.0.5->pyautogui)
    Downloading PyRect-0.2.0.tar.gz (17 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Collecting Pillow>=9.2.0 (from pyscreeze>=0.1.21->pyautogui)
    Downloading Pillow-9.5.0-cp37-cp37m-win_amd64.whl.metadata (9.7 kB)
    Collecting pyperclip (from mouseinfo->pyautogui)
    Downloading pyperclip-1.9.0.tar.gz (20 kB)
    Installing build dependencies … done
    Getting requirements to build wheel … done
    Installing backend dependencies … done
    Preparing metadata (pyproject.toml) … done
    Downloading Pillow-9.5.0-cp37-cp37m-win_amd64.whl (2.5 MB)
    —————————————- 2.5/2.5 MB 3.6 MB/s eta 0:00:00
    Building wheels for collected packages: pyautogui, pygetwindow, pyscreeze, pytweening, mouseinfo, pymsgbox, pyperclip, pyrect
    Building wheel for pyautogui (pyproject.toml) … done
    Created wheel for pyautogui: filename=PyAutoGUI-0.9.54-py3-none-any.whl size=37597 sha256=c1abe82b817f0466cc775863beb035dd6edf939b709c33b2d807b6e171d73ef3
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\ae\77\f1\c71436322c6e5e634523ea92f7e64ffbca2f1851b08d126193
    Building wheel for pygetwindow (pyproject.toml) … done
    Created wheel for pygetwindow: filename=PyGetWindow-0.0.9-py3-none-any.whl size=11080 sha256=aa154c2c924acaf3b397f7593dbf1b86b5c2275ed068452607ac26c916019288
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\91\7e\35\62d9062a06cfc46fea39e26860253da36f258b3f3fd96c91c3
    Building wheel for pyscreeze (pyproject.toml) … done
    Created wheel for pyscreeze: filename=PyScreeze-1.0.1-py3-none-any.whl size=14384 sha256=6ae8f717a83b3ce3fc4d6722a0694986b6d7a284d2cff1e9550df8456ecfefac
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\de\29\9f\92d5ceb93cbfcc465a154537bc16c0703b1d7955821fc2584c
    Building wheel for pytweening (pyproject.toml) … done
    Created wheel for pytweening: filename=pytweening-1.2.0-py3-none-any.whl size=8031 sha256=c6b10ca8de4e48e3a1aef16ccca2d8d3503bc48d4b8d72c153dc442bf5a38d01
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\9b\f6\cc\79ee5a508c9438397ef23111f30241ab0749ef93aebb077761
    Building wheel for mouseinfo (pyproject.toml) … done
    Created wheel for mouseinfo: filename=MouseInfo-0.1.3-py3-none-any.whl size=10904 sha256=fe19106b93c9d4112ada96b08ca09c0c86a60bfcfe9ab395ac7a5c689d303ce5
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\43\9a\7f\373736bf37b94b358be41fb2f317a0f9940a1dcb7a733e1707
    Building wheel for pymsgbox (pyproject.toml) … done
    Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7416 sha256=72fd25653fb3108d337876c653586013afc92d85fc573256cdf47aa7c9470350
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\39\eb\0e\1587e06da34adf675ad26a113da25df542991f5095303374ef
    Building wheel for pyperclip (pyproject.toml) … done
    Created wheel for pyperclip: filename=pyperclip-1.9.0-py3-none-any.whl size=11020 sha256=cb50e31f73e3ba7217889bf0d5486cb7e2d215f75d19a07d28357e3edfda93ca
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\63\35\9f\5d4ab53fbcd006beeebfd468ef530d0d25bb390b53bfb97f94
    Building wheel for pyrect (pyproject.toml) … done
    Created wheel for pyrect: filename=PyRect-0.2.0-py2.py3-none-any.whl size=11205 sha256=dab0ac51925ff7b1bcbe64f185e11d0169fabed9add58fd1a1b7db77130590be
    Stored in directory: c:\users\rkey\appdata\local\pip\cache\wheels\a8\c4\b9\73048d5fa590952161184f5367220620d40958f3c0b8e8c03d
    Successfully built pyautogui pygetwindow pyscreeze pytweening mouseinfo pymsgbox pyperclip pyrect
    Installing collected packages: pytweening, pyrect, pyperclip, pymsgbox, pygetwindow, Pillow, pyscreeze, mouseinfo, pyautogui
    Successfully installed Pillow-9.5.0 mouseinfo-0.1.3 pyautogui-0.9.54 pygetwindow-0.0.9 pymsgbox-1.0.9 pyperclip-1.9.0 pyrect-0.2.0 pyscreeze-1.0.1 pytweening-1.2.0