分类: 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库flask-2.2.5依赖

    Flask-2.2.5
    Jinja2-3.1.4
    click-8.1.7
    colorama-0.4.6
    flask-2.2.5
    importlib-metadata-6.7.0
    itsdangerous-2.1.2
    typing-extensions-4.7.1
    zipp-3.15.0


     

    Collecting flask
    Downloading https://files.pythonhosted.org/packages/9f/1a/8b6d48162861009d1e017a9740431c78d860809773b66cac220a11aa3310
    /Flask-2.2.5-py3-none-any.whl (101kB)
    100% |████████████████████████████████| 102kB 259kB/s
    Requirement already satisfied: Werkzeug>=2.2.2 in c:\users\rkey\source\repos\文件上传下载\env\lib\site-packages (from fl
    ask) (2.2.3)
    Collecting click>=8.0 (from flask)
    Downloading https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229
    /click-8.1.7-py3-none-any.whl (97kB)
    100% |████████████████████████████████| 102kB 1.1MB/s
    Collecting Jinja2>=3.0 (from flask)
    Downloading https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36
    /jinja2-3.1.4-py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 428kB/s
    Collecting itsdangerous>=2.0 (from flask)
    Downloading https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae
    /itsdangerous-2.1.2-py3-none-any.whl
    Collecting importlib-metadata>=3.6.0; python_version < “3.10” (from flask)
    Downloading https://files.pythonhosted.org/packages/ff/94/64287b38c7de4c90683630338cf28f129decbba0a44f0c6db35a873c73c4
    /importlib_metadata-6.7.0-py3-none-any.whl
    Requirement already satisfied: MarkupSafe>=2.1.1 in c:\users\rkey\source\repos\文件上传下载\env\lib\site-packages (from
    Werkzeug>=2.2.2->flask) (2.1.5)
    Collecting colorama; platform_system == “Windows” (from click>=8.0->flask)
    Downloading https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221
    /colorama-0.4.6-py2.py3-none-any.whl
    Collecting zipp>=0.5 (from importlib-metadata>=3.6.0; python_version < “3.10”->flask)
    Downloading https://files.pythonhosted.org/packages/5b/fa/c9e82bbe1af6266adf08afb563905eb87cab83fde00a0a08963510621047
    /zipp-3.15.0-py3-none-any.whl
    Collecting typing-extensions>=3.6.4; python_version < “3.8” (from importlib-metadata>=3.6.0; python_version < “3.10”->fl
    ask)
    Downloading https://files.pythonhosted.org/packages/ec/6b/63cc3df74987c36fe26157ee12e09e8f9db4de771e0f3404263117e75b95
    /typing_extensions-4.7.1-py3-none-any.whl
    Installing collected packages: zipp, typing-extensions, importlib-metadata, colorama, click, Jinja2, itsdangerous, flask

    Found existing installation: Jinja2 2.3.1
    Uninstalling Jinja2-2.3.1:
    Successfully uninstalled Jinja2-2.3.1
    Successfully installed Jinja2-3.1.4 click-8.1.7 colorama-0.4.6 flask-2.2.5 importlib-metadata-6.7.0 itsdangerous-2.1.2 t
    yping-extensions-4.7.1 zipp-3.15.0
    You are using pip version 18.1, however version 24.0 is available.
    You should consider upgrading via the ‘python -m pip install –upgrade pip’ command.

  • flask登录控制显示内容

    以下是登录和登出的逻辑

    @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('novel_index'))
            else:
                return 'Invalid username or password'
        return redirect(url_for('novel_index'))
    
    
    @app.route('/logout', methods=['GET', 'POST'])
    def logout():
        session.pop('logged_in', None)
        session.pop('username', None)
        return redirect(url_for('novel_index'))

    在登录后设置了session会话值

    session['logged_in'] = True

     

    在网页中获取这个值需要使用

    {% if session.logged_in %}

     

    实际案例如下

    {% if session.logged_in %}
        <!-- 登录表单,实际上用户已经登录,所以可以显示欢迎信息或其他内容 -->
        <form class="navbar-form pull-right" action="/logout" method="post">
            <button type="submit" class="btn">Logout</button>
        </form>
    {% else %}
        <!-- 登录表单 -->
        <form class="navbar-form pull-right" action="/login" method="post">
            <input class="span2" type="text" name="username" placeholder="Username">
            <input class="span2" type="password" name="password" placeholder="Password">
            <button type="submit" class="btn">Sign in</button>
        </form>
    {% endif %}

     

     

  • 获取当前所有进程 python

    # -*- coding: utf-8 -*-
    #!/usr/bin/env python3
    '''
    psutil==6.0.0
    '''
    import psutil
    import tkinter as tk
    from tkinter import ttk
    import socket
    # 定义一个函数来更新列表显示
    def update_list():
        # 获取搜索框中的文本
        search_text = search_entry.get().lower()
        listbox.delete(0, tk.END)  # 清空 listbox
        # 根据搜索文本更新列表显示
        for index, item in enumerate(get_all_processes()):
            if search_text in item.lower():
                if search_text in item.lower():  # 如果搜索文本在进程信息中
                    listbox.insert(tk.END, item)  # 将匹配的进程信息添加到 listbox
            else:
                listbox.selection_clear(index)
    def end_process():
        # 获取选中的进程 ID
        selection = listbox.curselection()
        if selection:
            index = int(selection[0])
            print('索引:',index)
            selection = listbox.get(selection)
            print('selection:',selection)
            parts = selection.split(", ")
            print('parts:',parts)
            # 检查 parts 列表是否有足够的元素
            # 若get_all_processes()函数的拼接方式出现改变,这里的截取方式都需要调整
            pid_part = parts[0].split(":")[1]  # 尝试获取 PID
            pid_part = int(pid_part)  # 将 PID 转换为整数
            name_part = parts[1].split(":")[1]  # "System Idle Process"
            username_part = parts[2].split(":")[1]  # "NT AUTHORITY\SYSTEM"
            print('pid_part:',pid_part,'name_part',name_part,'username_part',username_part)
            try:
                # 通过进程 ID 结束进程
                proc = psutil.Process(pid_part)
                proc.terminate()  # 发送终止信号
                listbox.delete(index)  # 从列表中删除进程项
            except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
                print(f"Error terminating process {pid_part}: {e}")
                listbox.delete(index)  # 从列表中删除进程项
          
    def get_all_processes():
        # 获取当前运行的所有进程的列表
        processes = psutil.process_iter(['pid', 'name', 'username'])
        proList=[]
        for proc in processes:
            try:
                pid = proc.info['pid']
                name = proc.info['name']
                username = proc.info['username']
                # 使用 net_connections() 获取网络连接信息
                # 这里因为获取了当前进程使用的所有端口号,所以可能会拖慢程序的速度,使用过程中的体验就是突然顿了一下又好了
                ports = set()
                for conn in psutil.net_connections(kind='inet'):
                    if conn.pid == pid and conn.type == socket.SOCK_STREAM and conn.status == 'ESTABLISHED':
                        ports.add(conn.laddr.port)
                ports_str = ', '.join(map(str, ports)) if ports else '无'
                process_info = f"进程ID:{pid}, 进程名:{name}, 进程所属用户名:{username}, 使用的端口号:{ports_str}"
                proList.append(process_info)
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                # 忽略已经结束的进程或访问被拒绝的进程
                pass
        return proList
    
    def center_window(window):
        screen_width = window.winfo_screenwidth()
        screen_height = window.winfo_screenheight()
        window_width = window.winfo_reqwidth()
        window_height = window.winfo_reqheight()
        x = (screen_width // 2) - (window_width // 2)
        y = (screen_height // 2) - (window_height // 2)
        window.geometry(f'+{x}+{y}')
    # 创建主窗口
    root = tk.Tk()
    root.title("Tkinter List Search")
    root.geometry("400x400")
    center_window(root)
    # 创建搜索框
    search_frame = tk.Frame(root)
    search_label = tk.Label(search_frame, text="Search:")
    search_label.pack(side=tk.LEFT)
    search_entry = tk.Entry(search_frame)
    search_entry.pack(side=tk.LEFT, expand=True, fill=tk.X)
    search_entry.bind("<Return>", lambda event: update_list())
    search_frame.pack(fill=tk.X)
    
    # 创建列表显示
    listbox = tk.Listbox(root)
    listbox.pack(fill=tk.BOTH, expand=True)
    
    # 填充列表
    for item in get_all_processes():
        print(item)
        listbox.insert(tk.END, item)
    
    # 搜索框获得焦点
    search_entry.focus()
    
    # 更新列表的函数绑定到搜索框的键入事件
    search_entry.bind("<KeyRelease>", lambda event: update_list())
    
    # 创建右键菜单
    right_click_menu = tk.Menu(root, tearoff=0)
    end_process_item = right_click_menu.add_command(label="结束进程", command=end_process)
    # 绑定右键点击事件到 Listbox
    listbox.bind("<Button-3>", lambda event: right_click_menu.post(event.x_root, event.y_root))
    
    if __name__ == "__main__":
        root.mainloop()

     

  • python压测工具locust

    from locust import HttpUser, task, between

    class WebsiteUser(HttpUser):
    wait_time = between(1, 2.5) # 用户之间请求的等待时间范围

    @task
    def view_video(self):
    url = “http://127.0.0.1/video/5-2 go语言的调度器”
    self.client.get(url, name=”/video/…”)

    # 注意:由于 URL 很长且包含特殊字符,我在这里简化了 name 参数以便在 Locust UI 中更容易识别

  • 图片格式转换 python

    from PIL import Image
    import os
    原图片路径 = input("需要转换的图片:")
    新图片路径 = input("新图片名,不写默认原名:")
    新图片格式 = input("新图片格式,不写默认PNG:")
    带后缀的文件名 = os.path.basename(原图片路径)
    不带后缀的文件名, _ = os.path.splitext(带后缀的文件名)
    if len(新图片格式) == 0:
        新图片格式='png'
    if len(新图片路径) == 0:
        if len(原图片路径.replace(带后缀的文件名,'')) == 0:
            新图片路径=不带后缀的文件名+'.'+新图片格式
        else:
            新图片路径=原图片路径.replace(带后缀的文件名,'\\')+不带后缀的文件名+'.'+新图片格式
    print(带后缀的文件名,不带后缀的文件名,新图片格式,新图片路径)
    with Image.open(原图片路径) as img:
        img.save(新图片路径, 新图片格式)

    ”’
    JPEG (.jpeg, .jpg): 使用 ‘JPEG’ 或 ‘JPG’ 作为格式参数。
    PNG (.png): 使用 ‘PNG’ 作为格式参数。
    GIF (.gif): 使用 ‘GIF’ 作为格式参数。
    TIFF (.tiff, .tif): 使用 ‘TIFF’ 或 ‘TIF’ 作为格式参数。
    BMP (.bmp, .dib): 使用 ‘BMP’ 作为格式参数。
    PPM (.ppm, .pbm, .pgm, .pnm): 使用 ‘PPM’ 作为格式参数。
    PSD (.psd): 使用 ‘PSD’ 作为格式参数。
    SGI (.sgi, .rgb, .rgba, .bw): 使用 ‘SGI’ 作为格式参数。
    TGA (.tga): 使用 ‘TGA’ 作为格式参数。
    XBM (.xbm): 使用 ‘XBM’ 作为格式参数。
    ”’

  • 代码发出声音 python

    import time
    import winsound
    
    # 设置频率和持续时间
    frequency = 37  # 频率,单位是Hz
    duration = 1000   # 持续时间,单位是毫秒
    
    # 发出声音
    winsound.Beep(frequency, duration)
    
    # 如果您想连续发出声音,可以使用循环
    try:
        while True:
            winsound.Beep(frequency, duration)
            time.sleep(1)  # 暂停一秒
    except KeyboardInterrupt:
        # 允许使用Ctrl+C中断循环
        print("声音停止")

    修改频率可得到不同的声音,

    频率的最大值是:37Hz

    最小值是32767Hz

    import winsound
    import time
    
    # 定义每个音符的频率(以Hz为单位)和持续时间(毫秒)
    notes = {
        'C4': 261.63,
        'D4': 293.66,
        'E4': 329.63,
        'F4': 349.23,
        'G4': 392.00,
        'A4': 440.00,
        'B4': 493.88,
        'C5': 523.25
    }
    
    # 音符持续时间(毫秒)
    duration = 500
    
    # 四分音符的频率值,转换为整数
    note_frequencies = {note: int(frequency) for note, frequency in notes.items()}
    
    # 一个简化的主旋律,用音符名称表示
    melody = [
        'C4', 'E4', 'G4', 'C5',
        'B4', 'A4', 'G4', 'F4',
        'E4', 'D4', 'C4',
        'A4', 'G4', 'F4', 'E4'
    ]
    
    # 演奏旋律
    for note in melody:
        frequency = note_frequencies[note]
        winsound.Beep(frequency, duration)  # 发出音符
        time.sleep(duration / 1000.0)  # 等待音符结束
    
    # 等待旋律结束后再退出
    time.sleep(2)

    import winsound
    import time
    
    # 定义每个音符的频率(以Hz为单位)和持续时间(毫秒)
    notes = [
        {"frequency": 262, "duration": 500},  # C5
        {"frequency": 294, "duration": 500},  # D5
        {"frequency": 330, "duration": 500},  # E5
        {"frequency": 349, "duration": 1500}, # F5 (held longer)
        {"frequency": 392, "duration": 500},  # G5
        {"frequency": 440, "duration": 500},  # A5
        {"frequency": 494, "duration": 500}   # B5
    ]
    
    # 定义休止符(无声)
    rest = {"frequency": 0, "duration": 500}
    
    # 旋律序列,每个元素是一个索引到notes列表
    melody = [0, 1, 2, 3, 2, 1, 0, 2, 3, 2, 1, 0, 0, 2, 2, 1, 0]
    
    # 演奏旋律
    for note_index in melody:
        if note_index != -1:
            note = notes[note_index]
            winsound.Beep(note["frequency"], note["duration"])
        else:
            time.sleep(rest["duration"] / 1000.0)  # 休息片刻
    
        # 等待每个音符结束后再继续
        time.sleep(0.5)  # 等待半秒钟

     

  • data.get和request.form.get

    request.form.get('书籍作者')data.get('title', book.title) 这两行代码都用于从 HTTP 请求中获取数据,但它们在用法和上下文中存在一些差异:

    1. 数据来源
      • request.form.get('书籍作者'):这行代码用于从 Flask 的 request.form 属性中获取数据,request.form 是一个类似于字典的对象,包含了客户端通过 application/x-www-form-urlencoded  multipart/form-data 编码类型提交的表单数据。
      • data.get('title', book.title):这行代码中的 data 通常是一个从 request.get_json() 解析得到的 JSON 对象,get 方法用于从 JSON 对象中获取数据。如果指定的键(在这个例子中是 'title')存在,则返回其对应的值;如果不存在,则返回默认值 book.title
    2. 数据类型
      • request.form.get() 方法返回的数据类型取决于表单字段的数据类型,通常是字符串。
      • data.get() 方法返回的数据类型取决于 JSON 对象中的数据类型,可能是字符串、数字、布尔值、列表或字典等。
    3. 默认值
      • request.form.get('书籍作者') 没有提供默认值的参数,如果在表单数据中没有找到 '书籍作者' 键,将返回 None
      • data.get('title', book.title) 明确提供了默认值 book.title,如果在 JSON 数据中没有找到 'title' 键,将使用书籍当前的标题作为默认值。
    4. 使用场景
      • 当您处理一个包含表单数据的 POST 请求时,通常会使用 request.form.get() 来获取数据。
      • 当您处理一个发送 JSON 数据的 POST 请求时,通常会使用 request.get_json() 来解析数据,然后使用 data.get() 来获取特定的字段。
    5. 编码类型
      • request.form 适用于处理 URL 编码的表单数据(例如,来自一个带有 <input> 元素的 HTML 表单)。
      • request.get_json() 适用于处理 JSON 编码的数据(例如,来自一个使用 AJAX 或其他 JavaScript 方法发送 JSON 格式数据的前端应用)。

    在实际应用中,选择哪种方法取决于您的具体需求和客户端发送的数据格式。如果您的 Flask 应用期望接收 JSON 格式的请求体,那么使用 request.get_json()data.get() 是合适的;如果您的表单使用传统的表单提交方式,那么使用 request.form.get() 会更合适。

  • bat脚本启动py虚拟环境

    bat脚本启动虚拟环境

    chcp 65001
    @echo off
    title 电子书管理
    
    :: 激活虚拟环境
    call .\.venv\Scripts\activate.bat
    
    :: 运行 Python 应用程序
    python app.py
    
    :: 暂停,等待用户按键后关闭窗口
    pause

     

  • flask 分页

    <nav class="blog-pagination" aria-label="Pagination">
    {% if paginate.has_prev %}
    <a class="btn btn-outline-primary rounded-pill" href="{{ url_for('index.index', page=paginate.prev_num) }}">上一页</a>
    {% else %}
    <a class="btn btn-outline-primary rounded-pill" href="#">上一页</a>
    {% endif %}
    
    <!-- 显示所有存在的页码 -->
    {% for num in range(1, paginate.pages + 1) %}
    <a class="btn btn-outline-primary rounded-pill {% if num == paginate.page %}active{% endif %}" href="#">{{ num }}</a>
    {% endfor %}
    
    {% if paginate.has_next %}
    <a class="btn btn-outline-secondary rounded-pill" href="{{ url_for('index.index', page=paginate.next_num) }}">下一页</a>
    {% else %}
    <a class="btn btn-outline-secondary rounded-pill disabled">下一页</a>
    {% endif %}
    </nav>

     

  • py 视频转码

    需要你电脑本身安装的有FFmpeg,你下载的压缩包形式的话,记得把里面的bin路径加入到电脑环境变量里,不然无法识别

    功能:

    在视频同目录下转码成mp4文件

    # 指定要搜索的目录路径
    输入文件路径 = r‘E:\阿里云盘下载\Oracle合集\ORACLE视频教学’
    import subprocess,os,json
    
    def ffprobe_get_info(输入文件路径):
        """使用ffprobe获取视频文件的元数据信息"""
        try:
            probe = subprocess.run(['ffprobe', '-v', 'error', '-show_entries', 'format=duration,size:stream=width,height,avg_frame_rate', '-of', 'json', 输入文件路径], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            if probe.returncode != 0:
                print(f"ffprobe error: {probe.stderr.decode()}")
                return None
            return json.loads(probe.stdout)
        except Exception as e:
            print(f"An error occurred: {e}")
            return None
    
    def 自动转码视频(输入文件路径, 输出文件路径):
        """使用ffprobe和ffmpeg自动转码视频"""
        video_info = ffprobe_get_info(输入文件路径)
    
        # 寻找第一个具有有效宽度和高度信息的流
        for stream in video_info['streams']:
            if 'width' in stream and 'height' in stream:
                width = stream['width']
                height = stream['height']
                fps = stream['avg_frame_rate'].split('/')[0]
                break
        else:
            print('未找到有效的视频流')
            return False  # 如果没有找到有效的流,则返回False
    
        duration = float(video_info['format']['duration'])
    
        # 计算视频比特率,这里假设为文件大小的85%,您可以根据需要调整
        file_size = os.path.getsize(输入文件路径)
        video_bitrate = int(0.85 * (file_size * 8 / duration))
    
        # 构建FFmpeg转码命令
        ffmpeg命令 = [
            'ffmpeg',
            '-err_detect', 'ignore_err',  # 添加错误容错选项
            '-i', 输入文件路径,
            '-vcodec', 'h264',
            '-acodec', 'aac',
            '-strict', 'experimental',
            '-movflags', '+faststart',
            '-b:v', f'{video_bitrate}k',
            '-vf', f"scale=-2:{height}",  # 使用height变量
            '-b:a', '128k',
            '-ac', '2',
            '-r', fps,
        ] + [输出文件路径]  # 将输出文件路径添加到命令列表中
    
        # 运行FFmpeg命令
        try:
            subprocess.run(ffmpeg命令, check=True)
            print('视频转码成功')
            return True
        except subprocess.CalledProcessError:
            print('视频转码失败')
            return False
    
    
    # 获取指定文件夹所有非mp4文件绝对路径
    def 获取所有非mp4文件路径(目录路径, 视频格式列表):
        非mp4文件列表 = []
        # 排除 'mp4' 格式
        非mp4格式列表 = [格式 for 格式 in 视频格式列表 if 格式 != 'mp4']
        # 遍历目录
        for root, dirs, files in os.walk(目录路径):
            for 文件名 in files:
                文件扩展名 = 文件名.lower().rsplit('.', 1)[-1]  # 获取文件扩展名
                if 文件扩展名 in 非mp4格式列表:
                    非mp4文件列表.append(os.path.join(root, 文件名))
        return 非mp4文件列表
    
    # 定义支持的视频格式列表
    video_formats = [
        'rmvb','avi', 'mov', 'wmv', 'flv', 'mkv', 'rm',
        'asf', 'mpg', '3gp', 'vob', 'm4v', 'f4v', 'webm',
        'm2ts', 'ts', 'divx', 'xvid', 'mxf'
    ]
    
    # 指定要搜索的目录路径
    输入文件路径 = r'E:\阿里云盘下载\Oracle合集\ORACLE视频教学'
    
    # 获取所有非mp4格式的视频文件路径
    所有非mp4文件路径列表 = 获取所有非mp4文件路径(输入文件路径, video_formats)
    
    # 对每个非mp4格式的视频文件执行转码操作
    for 单个非mp4文件路径 in 所有非mp4文件路径列表:
        try:
            # 构造新的mp4文件路径
            输出文件路径 = os.path.splitext(单个非mp4文件路径)[0] + '.mp4'
            print(单个非mp4文件路径)
            print(输出文件路径)
            # 执行转码操作
            自动转码视频(单个非mp4文件路径, 输出文件路径)
            # 如果转码成功,删除原始文件
            # os.remove(单个非mp4文件路径)
            print(f"原始文件已转码完成: {单个非mp4文件路径}")
            # print(f"已删除原始文件: {单个非mp4文件路径}")
        except Exception as e:
            print(f"处理文件 {单个非mp4文件路径} 时发生错误: {e}")