C语言调用【Python3】

news2024/11/25 10:41:02

一、搭建编译环境

  • 终端查询系统及软件版本
  • dpkg -l 列出所有已安装的软件包

二、C语言中调用Python

  • 使用 GCC编译并链接 Python 3.10 的共享库
  • 如何在C中获取和修改 sys.path

三、C语言调用无参python函数
四、C语言调用有参python函数

一、搭建编译环境

通过C语言调用Python代码,需要先安装libpython3的 dev依赖库(不同的ubuntu版本下,python版本可
能会有差异, 比如ubuntu 22.04里是libpython3.10-dev)。

libpython3 通常指的是 Python 3 的共享库文件(shared library)。在 Linux 系统上,这个库文件的名称可能会有所不同,通常是以 libpython3.x.so 的形式命名,其中 x 是 Python 3 的主版本号。

如果你希望在编译时链接 Python 3 的共享库,你需要确保已经安装了对应版本的 Python 3 开发包。这通常包括了 Python 3 的头文件和共享库文件。你可以使用系统的包管理工具来安装这些开发包。

以下是在一些流行的 Linux 发行版上安装 Python 3 开发包的示例:

  • 在 Ubuntu 或者 Debian 上:

    sudo apt-get update
    sudo apt-get install python3-dev
    
  • 在 Fedora 上:

    sudo dnf install python3-devel
    
  • 在 CentOS 或者 RHEL 上:

    sudo yum install python3-devel
    

一旦你安装了 Python 3 的开发包,你就应该能够在系统中找到 libpython3.x.so 文件,其中 x 是你安装的 Python 3 的主版本号。这个文件通常位于 /usr/lib//usr/lib64/ 目录下。

请注意,如果你在编译时使用 gcc 或其他编译器,你可能需要使用 -lpython3.x 标志来链接 Python 3 的共享库。例如:

gcc -o my_program my_program.c -I/usr/include/python3.x -lpython3.x

请替换 3.x 为你所使用的 Python 3 的版本号。

终端查询系统及软件版本

这些命令用于检查内核版本、系统信息、Python版本、GCC版本和Linux发行版信息。

以下是每个命令的简要说明:

  1. cat /proc/version 显示Linux内核版本和系统信息。

  2. cat /etc/issue 打印/etc/issue文件的内容,该文件通常包含有关Linux发行版的信息。

  3. uname -a 打印系统信息,如内核名称、网络节点主机名、内核发布版本、内核版本、机器硬件名称和处理器类型。

  4. python --version 显示Python解释器的版本。

  5. gcc -v 显示GCC(GNU编译器集合)的版本。

  6. lsb_release -a 打印LSB(Linux标准基础)和特定于发行版的信息。LSB是一组标准,旨在增加Linux发行版之间的兼容性。

您可以在终端中运行这些命令来查看有关您的Linux系统的相应信息。 请记住,这些命令的可用性和输出可能会有所不同,具体取决于您的特定 Linux 发行版和系统配置。

dpkg -l 列出所有已安装的软件包

这个命令用于列出已安装的与 Python 3 开发相关的库。具体来说,它使用 dpkg -l 列出所有已安装的软件包,然后使用 grep 过滤出包含 “libpython3” 和 “dev” 的行。

在 Ubuntu 或 Debian 等基于 Debian 的系统上,你可以运行以下命令:

dpkg -l | grep libpython3 | grep dev

如果你已经安装了 Python 3 的开发包,命令的输出应该包含与 Python 3 相关的开发库。如果没有安装,输出将为空。

请注意,这是一种查找已安装软件包的方法,确保你使用了适用于你的 Linux 发行版的包管理工具。

二、C语言中调用Python

在C语言中调用Python代码通常涉及到使用Python的C API。Python提供了一组C API,允许在C中调用Python函数、处理Python对象等。

下面是一个简单的例子,展示了如何在C中调用Python代码:

  1. Python脚本: 编写一个简单的Python脚本,保存为 example.py

    # example.py
    def add_numbers(a, b):
        return a + b
    
  2. C代码: 编写一个C程序 invoke.c,调用Python中的函数。

    #include <Python.h>
    
    int main() {
        // 初始化Python解释器
        Py_Initialize();
    
        // 导入Python模块
        PyObject* pModule = PyImport_ImportModule("example");
    
        if (pModule != NULL) {
            // 获取Python函数对象
            PyObject* pFunction = PyObject_GetAttrString(pModule, "add_numbers");
    
            if (pFunction != NULL) {
                // 调用Python函数
                PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(3), PyLong_FromLong(5));
                PyObject* pResult = PyObject_CallObject(pFunction, pArgs);
    
                if (pResult != NULL) {
                    // 处理Python函数的返回值
                    printf("Result: %ld\n", PyLong_AsLong(pResult));
                    Py_DECREF(pResult);
                } else {
                    PyErr_Print(); // 打印Python错误信息
                }
    
                Py_DECREF(pFunction);
                Py_DECREF(pArgs);
            } else {
                PyErr_Print();
            }
    
            Py_DECREF(pModule);
        } else {
            PyErr_Print();
        }
    
        // 关闭Python解释器
        Py_Finalize();
    
        return 0;
    }
    
  3. 编译: 使用合适的编译器将C代码编译成可执行文件。

    gcc invoke.c -o invoke -I /usr/include/python3.x -l python3.x
    gcc -o simpledemo simpledemo.c -I /usr/include/python3.x -l python3.x
    

    请确保替换 3.x 为你所使用的Python版本号。

  4. 运行: 运行生成的可执行文件。

    ./invoke
    

这个例子中,C程序初始化了Python解释器,导入了一个Python模块,获取了Python模块中的一个函数,调用了这个函数,并处理了Python函数的返回值。这只是一个简单的例子,实际应用可能涉及更复杂的交互和数据传递。

使用 GCC编译并链接 Python 3.10 的共享库

这段命令和代码的作用是:

  1. ls /usr/include/python:列出 /usr/include/python 目录下的内容。通常,Python 的头文件(.h 文件)会在这个目录下。

  2. gcc invoke.c -o invoke -I /usr/include/python3.10 -lpython3.10:使用 GCC 编译 invoke.c 文件,并链接 Python 3.10 的共享库。其中,-I 选项指定了头文件所在的目录,-lpython3.10 用于链接 Python 3.10 的共享库。编译后的可执行文件名为 invoke

  3. ./invoke:运行编译生成的 invoke 可执行文件。

这段命令和代码的目的可能是在 invoke.c 文件中调用了 Python 3.10 的一些函数,并通过 GCC 编译器将其与 Python 3.10 的共享库链接起来。在运行 invoke 可执行文件时,它可能会执行 invoke.c 中的 Python 相关代码。

请确保你的系统中已经安装了 Python 3.10 的开发包,以及 GCC 编译器。如果没有安装,你可以使用系统的包管理工具进行安装。

如何在C中获取和修改 sys.path

sys.path列表里储存了python默认库搜索路径

在Python中,sys.path 是一个包含模块搜索路径的列表。当你导入一个模块时,Python会在这些路径中查找模块文件。

在C语言中,你可以通过Python/C API来获取和操作 sys.path。以下是一个简单的例子,展示了如何在C中获取和修改 sys.path

#include <Python.h>

int main() {
    // 初始化Python解释器
    Py_Initialize();

    // 获取sys.path对象
    PyObject* sysPath = PySys_GetObject("path");

    // 打印原始sys.path
    printf("Original sys.path:\n");
    for (Py_ssize_t i = 0; i < PyList_Size(sysPath); ++i) {
        PyObject* pathItem = PyList_GetItem(sysPath, i);
        const char* pathStr = PyUnicode_AsUTF8(pathItem);
        printf("%s\n", pathStr);
    }

    // 添加新路径到sys.path
    PyList_Append(sysPath, PyUnicode_DecodeFSDefault("/path/to/your/directory"));

    // 打印修改后的sys.path
    printf("\nModified sys.path:\n");
    for (Py_ssize_t i = 0; i < PyList_Size(sysPath); ++i) {
        PyObject* pathItem = PyList_GetItem(sysPath, i);
        const char* pathStr = PyUnicode_AsUTF8(pathItem);
        printf("%s\n", pathStr);
    }

    // 关闭Python解释器
    Py_Finalize();

    return 0;
}

这个例子中,我们使用 PySys_GetObject("path") 获取了 sys.path 对象,并使用 PyList_Append 将新的路径添加到列表中。在实际应用中,你可能会根据你的需求添加不同的路径。请注意,在真实的应用中,你可能需要更加谨慎地处理路径,以确保不会破坏系统的正常运行。

#!/usr/bin/python3

import sys

print(sys.path)

在这里插入图片描述

三、C语言调用无参python函数

C语言中调用无参Python函数的步骤

1、包含Python.h头文件,以便使用Python API。

2、使用void Py_Initialize()初始化Python解释器,

3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)
获取sys.path对象,并利用int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,
以便加载当前的Python模块(Python文件即python模块)。

4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否有错误。

5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取Python函数对象,并检查是否可调用。

6、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用Python函数,并获取返回值。

7、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。

8、结束时调用void Py_Finalize()函数关闭Python解释器。

相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
3.10 Documentation » Python/C API 参考手册 » 工具 » 导入模块

#include <Python.h>

int main() {
    // 1. 初始化Python解释器
    Py_Initialize();

    // 2. 获取sys.path对象,并将当前路径添加到sys.path中
    PyObject* sysPath = PySys_GetObject("path");
    PyList_Append(sysPath, PyUnicode_DecodeFSDefault("."));

    // 3. 导入Python模块
    PyObject* pModule = PyImport_ImportModule("your_module_name");

    if (pModule != NULL) {
        // 4. 获取Python函数对象
        PyObject* pFunction = PyObject_GetAttrString(pModule, "your_function_name");

        if (pFunction != NULL && PyCallable_Check(pFunction)) {
            // 5. 调用Python函数(这里是无参数调用)
            PyObject* pArgs = PyTuple_New(0);  // 传递空参数元组
            PyObject* pResult = PyObject_CallObject(pFunction, pArgs);

            if (pResult != NULL) {
                // 6. 处理返回值,可以在这里进行你的操作
                Py_DECREF(pResult);
            } else {
                // 打印Python错误信息
                PyErr_Print();
            }

            // 释放Python函数对象和参数
            Py_DECREF(pFunction);
            Py_DECREF(pArgs);
        } else {
            // 打印Python错误信息
            PyErr_Print();
        }

        // 释放Python模块对象
        Py_DECREF(pModule);
    } else {
        // 打印Python错误信息
        PyErr_Print();
    }

    // 7. 关闭Python解释器
    Py_Finalize();

    return 0;
}

请确保替换 “your_module_name” 和 “your_function_name” 为你实际使用的Python模块和函数的名称。
这段代码演示了如何在C中调用一个无参数的Python函数。

根据上面的流程写出的示例代码如下:

# nopara.py文件
# !/usr/bin/python3

def say_funny():
  print('funny')
#include <Python.h>

int main()
{
  // 1. 初始化Python解释器
  Py_Initialize();
    
  // 2. 获取sys.path对象,并将当前路径添加到sys.path中
  PyObject *sys = PyImport_ImportModule("sys");
  PyObject *path = PyObject_GetAttrString(sys, "path");
  PyList_Append(path, PyUnicode_FromString(".")); // PyUnicode_FromString将c字符串转换成Python字符串
  
  // 3. 导入Python模块
  PyObject *pModule = PyImport_ImportModule("nopara");
  
  if (!pModule) {
    PyErr_Print();
    printf("ERROR: failed to load nopara.py\n");
    
    return 1;
  }
  
  // 4. 获取Python函数对象say_funny
  PyObject *pFunc = PyObject_GetAttrString(pModule, "say_funny");
  
  if (!pFunc || !PyCallable_Check(pFunc)) {
    PyErr_Print();
    printf("ERROR: function say_funny not found or not callable\n");
    
    return 1;
  }

  // 5. 调用Python函数,调用say_funny函数并获取返回值
  PyObject *pValue = PyObject_CallObject(pFunc, NULL);
  
  if (!pValue ) {
    PyErr_Print();
    printf("ERROR: function call failed\n");
    
    return 1;
  }
  
  // 释放所有引用的Python对象
  Py_DECREF(pValue);
  Py_DECREF(pFunc);
  Py_DECREF(pModule);
  
  // 关闭Python解释器
  Py_Finalize();
  
  return 0;
}

编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本):

gcc -o nopara nopara.c -I /usr/include/python3.10/ -l python3.10
./nopara

在这里插入图片描述

四、C语言调用有参python函数

C语言中调用有参Python函数的步骤

1、包含Python.h头文件,以便使用Python API。

2、使用void Py_Initialize()初始化Python解释器,

3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)
获取sys.path对象,并利用int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,
以便加载当前的Python模块(Python文件即python模块)。

4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否有错误。

5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取Python函数对象,并检查是否可调用。

6、使用PyObject *Py_BuildValue(const char *format, …)函数将C类型的数据结构转换成Python对象,
作为Python函数的参数,没有参数不需要调用

7、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用Python函数,并获取返回值。

8、使用int PyArg_Parse(PyObject *args, const char *format, …)函数将返回值转换为C类型,
并检查是否有错误,没有返回值时不需要调用

9、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。

10、结束时调用void Py_Finalize()函数关闭Python解释器。

相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
3.12.0 Documentation » Python/C API 参考手册 » 工具 » 导入模块

在C语言中调用有参Python函数的步骤。这里是整理后的步骤:

#include <Python.h>

int main() {
    // 1. 初始化Python解释器
    Py_Initialize();

    // 2. 获取sys.path对象,并将当前路径添加到sys.path中
    PyObject* sysPath = PySys_GetObject("path");
    PyList_Append(sysPath, PyUnicode_DecodeFSDefault("."));

    // 3. 导入Python模块
    PyObject* pModule = PyImport_ImportModule("your_module_name");

    if (pModule != NULL) {
        // 4. 获取Python函数对象
        PyObject* pFunction = PyObject_GetAttrString(pModule, "your_function_name");

        if (pFunction != NULL && PyCallable_Check(pFunction)) {
            // 5. 构建Python函数的参数
            PyObject* pArgs = Py_BuildValue("(ii)", 42, 17);  // 传递两个整数参数

            if (pArgs != NULL) {
                // 6. 调用Python函数
                PyObject* pResult = PyObject_CallObject(pFunction, pArgs);

                if (pResult != NULL) {
                    // 7. 处理返回值,可以在这里进行你的操作

                    // 8. 将返回值转换为C类型
                    int resultValue;
                    if (PyArg_Parse(pResult, "i", &resultValue)) {
                        // 处理resultValue
                    } else {
                        // 转换错误
                        PyErr_Print();
                    }

                    Py_DECREF(pResult);
                } else {
                    // 打印Python错误信息
                    PyErr_Print();
                }

                // 释放Python函数对象和参数
                Py_DECREF(pFunction);
                Py_DECREF(pArgs);
            } else {
                // 参数构建错误
                PyErr_Print();
            }
        } else {
            // 打印Python错误信息
            PyErr_Print();
        }

        // 释放Python模块对象
        Py_DECREF(pModule);
    } else {
        // 打印Python错误信息
        PyErr_Print();
    }

    // 9. 关闭Python解释器
    Py_Finalize();

    return 0;
}

请确保替换 “your_module_name” 和 “your_function_name” 为你实际使用的Python模块和函数的名称,并根据你的函数参数类型调整 Py_BuildValuePyArg_Parse 的格式字符串。

第六步传参

6、使用PyObject *Py_BuildValue(const char *format, …)函数创建一个Python元组或者对象,
作为Python函数的参数,没有参数势不需要调用

这里要注意的是,Py_BuildValue的第一个参数是类型转换:C对应的Python的数据类型转换对应的格式如下:
在这里插入图片描述

Py_BuildValue 函数用于将C中的数据转换为Python对象。它的第一个参数是一个格式字符串,指定了如何构建Python对象。以下是一些常见的格式码及其对应的C数据类型:

  • 's':字符串
    • C类型:const char*
  • 'i':整数
    • C类型:int
  • 'l':长整数
    • C类型:long
  • 'f':浮点数
    • C类型:double
  • 'd':双精度浮点数
    • C类型:double
  • 'O':任意Python对象
    • C类型:PyObject*

例如,如果你想构建一个Python元组,其中包含一个整数和一个字符串,可以使用以下格式字符串:

PyObject* result = Py_BuildValue("(is)", 42, "hello");

这将构建一个包含一个整数和一个字符串的元组。第一个参数 42 对应 i 表示整数,第二个参数 "hello" 对应 s 表示字符串。

以下是一些常用的格式码:

  • '()':元组
  • '[]':列表
  • '{}':字典
  • 's':字符串
  • 'i':整数
  • 'l':长整数
  • 'f':浮点数
  • 'd':双精度浮点数
  • 'O':任意Python对象

你可以根据实际需要选择合适的格式码,并使用相应的C数据类型提供参数。
确保在使用 Py_BuildValue 时,提供的参数数量和格式码匹配,以避免运行时错误。

格式码C数据类型示例
's'const char*Py_BuildValue("s", "hello")
'i'intPy_BuildValue("i", 42)
'l'longPy_BuildValue("l", 123456789L)
'f'floatPy_BuildValue("f", 3.14f)
'd'doublePy_BuildValue("d", 2.71828)
'O'PyObject*Py_BuildValue("O", somePyObject)
'()'TuplePy_BuildValue("(is)", 42, "hello")
'[]'ListPy_BuildValue("[i]", 1)
'{}'DictionaryPy_BuildValue("{s:i}", "key", 42)
## 第八步返回值的处理 8、使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类型, 并检查是否有错误,**没有返回值时不需要调用**。

PyArg_Parse 是 Python/C API 中用于将 Python 对象参数转换为 C 数据类型的函数。它通常用于解析从 Python 调用的函数传递的参数。以下是 PyArg_Parse 的基本用法:

int PyArg_Parse(PyObject *args, const char *format, ...);
  • args: 一个包含传递给函数的参数的元组。
  • format: 包含格式化指令的字符串,指定了如何解析参数。
  • ...: 用于接收解析后的参数值的变量。

PyArg_Parse 的格式化指令可以是以下之一:

  • 'i': 整数
  • 'f': 浮点数
  • 's': 字符串
  • 'O': 任意对象

以下是一些示例:

  1. 解析一个整数参数:

    int value;
    if (!PyArg_Parse(args, "i", &value)) {
        // 处理解析错误
        return NULL;
    }
    
  2. 解析一个浮点数参数:

    double value;
    if (!PyArg_Parse(args, "f", &value)) {
        // 处理解析错误
        return NULL;
    }
    
  3. 解析一个字符串参数:

    const char *text;
    if (!PyArg_Parse(args, "s", &text)) {
        // 处理解析错误
        return NULL;
    }
    
  4. 解析一个任意对象参数:

    PyObject *obj;
    if (!PyArg_Parse(args, "O", &obj)) {
        // 处理解析错误
        return NULL;
    }
    

PyArg_Parse 还支持更复杂的格式化字符串,允许你指定多个参数以及它们的类型。例如:

int x, y;
if (!PyArg_Parse(args, "(ii)", &x, &y)) {
    // 处理解析错误
    return NULL;
}

在这个例子中,期望参数是一个包含两个整数的元组。

注意:PyArg_Parse 在解析参数时会自动增加引用计数,但在解析失败时需要手动处理错误。如果解析失败,它会返回 0,并且你应该在错误处理中返回 NULL 或适当的错误信息。

示例代码如下:

# para.py文件
# !/usr/bin/python3

def say_funny(category):
  print(category)
  return category    
#if 0
1、包含Python.h头文件,以便使用Python API。

2、使用void Py_Initialize()初始化Python解释器,

3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)
获取sys.path对象,并利用int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,
以便加载当前的Python模块(Python文件即python模块)4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否有错误。

5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取Python函数对象,并检查是否可调用。

6、使用PyObject *Py_BuildValue(const char *format, ...)函数将C类型的数据结构转换成Python对象,
作为Python函数的参数,没有参数不需要调用。

7、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用Python函数,并获取返回值。

8、使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类型,
并检查是否有错误,没有返回值时不需要调用。

9、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。

10、结束时调用void Py_Finalize()函数关闭Python解释器。

相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
https://docs.python.org/zh-cn/3/c-api/import.html
#endif

#include <Python.h>

int main()
{
  // 初始化Python解释器
  Py_Initialize();
    
  // 获取sys.path对象,并将当前路径添加到sys.path中
  PyObject *sys = PyImport_ImportModule("sys");
  PyObject *path = PyObject_GetAttrString(sys, "path");
  PyList_Append(path, PyUnicode_FromString(".")); // PyUnicode_FromString将c字符串转换成Python字符串
  
  // 导入Python模块
  PyObject *pModule = PyImport_ImportModule("para");
  
  if (!pModule ) {
    PyErr_Print();
    printf("ERROR: failed to load para.py\n");
    
  }
  
  // 获取Python函数对象say_funny
  PyObject *pFunc = PyObject_GetAttrString(pModule, "say_funny");
  
  if (!pFunc || !PyCallable_Check(pFunc)) {
    PyErr_Print();
    printf("ERROR: function say_funny not found or not callable\n");
    
    return 1;
  }

  //创建一个字符串作为参数
  char *category = "comedy";
  PyObject *pArgs = Py_BuildValue("(s)", category);
  
  // 调用Python函数,调用say_funny函数并获取返回值
  PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
  
  if (!pValue) {
    PyErr_Print();
    printf("ERROR: function call failed\n");
  }
  
  //将返回值转换为C类型
  char *result = NULL;
  
  if (!PyArg_Parse(pValue, "s", &result)) {
    PyErr_Print();
    printf("Error: parse failed\n");
  }
  
  //打印返回值
  printf("pValue=%s\n", result);  
  
  // 释放所有引用的Python对象
  Py_DECREF(pValue);
  Py_DECREF(pFunc);
  Py_DECREF(pModule);
  
  // 关闭Python解释器
  Py_Finalize();
  
  return 0;
}

编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本):

gcc para.c -o para -I /usr/include/python3.10 -l python3.10
./para

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1219758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PT Plugin Plus(PT助手、种子下载)扩展程序安装教程

PT助手 PT 助手 Plus&#xff0c;是一款浏览器插件&#xff08;Web Extensions&#xff09;&#xff0c;主要用于辅助下载 PT 站的种子。 适用于各 PT 站&#xff0c;可使下载种子等各项操作变化更简单、快捷。配合下载服务器&#xff08;如 Transmission、Torrent 等&#x…

电源线虚接,导致信号线发烫

音频板的信号是经过隔直电容接到音频板的。

VRRP专题

一&#xff0c;VRRP&#xff1a;虚拟路由冗余协议 将多个路由设备联合组成一台虚拟的路由设备&#xff0c;这台虚拟的路由设备做用户的网关&#xff0c;转发数据&#xff1b;这台虚拟的设备的网关由一个高优先级的设备承载&#xff0c;该设备被称为master路由器&#xff0c;其…

OpenCV快速入门:像素操作和图像变换

文章目录 前言1. 像素操作1.1 像素统计1.2 两个图像之间的操作1.2.1 图像加法操作1.2.3 图像加权混合 1.3 二值化1.4 LUT&#xff08;查找表&#xff09;1.4.1 查找表原理1.4.2 代码演示 2 图像变换2.1 旋转操作2.1.1 旋转的基本原理2.1.2 代码实现 2.2 缩放操作2.3 平移操作2.…

大数据-之LibrA数据库系统告警处理(ALM-12050 网络写吞吐率超过阈值)

告警解释 系统每30秒周期性检测网络写吞吐率&#xff0c;并把实际吞吐率和阈值&#xff08;系统默认阈值80%&#xff09;进行比较&#xff0c;当检测到网络写吞吐率连续多次&#xff08;默认值为5&#xff09;超过阈值时产生该告警。 用户可通过“系统设置 > 阈值配置 >…

【容器化】Kubernetes(k8s)

文章目录 概述Docker 的管理痛点什么是 K8s云架构 & 云原生 架构核心组件K8s 的服务注册与发现组件调用流程部署单机版部署主从版本Operator来源拓展阅读 概述 Docker 虽好用&#xff0c;但面对强大的集群&#xff0c;成千上万的容器&#xff0c;突然感觉不香了。 这时候就…

Molecular Plant | ChIP-seq+RNA-seq解析E2F转录因子在植物复制胁迫响应中的独特和互补作用

生物体的生存完全依赖于它们对基因组完整性的维持&#xff0c;而基因组完整性受到增殖细胞复制胁迫的永久威胁。尽管植物DNA损伤反应&#xff08;DDR&#xff09;调节因子SOG1已被证明能够应对复制缺陷&#xff0c;但越来越多的证据表明&#xff0c;还有其他途径独立于SOG1发挥…

Python爬虫动态ip代理防止被封的方法

目录 前言 一、什么是动态IP代理&#xff1f; 二、如何获取代理IP&#xff1f; 1. 付费代理IP 2. 免费代理IP 3. 自建代理IP池 三、如何使用代理IP爬取数据&#xff1f; 1. 使用requests库设置代理IP 2. 使用urllib库设置代理IP 3. 使用selenium库设置代理IP 四、常…

C/C++ 字符 - ‘0‘ 或者 + ‘0‘ 的含义及区别(从ASCII码深度解析,小白一看就懂!!!)

目录 一、前言 二、什么是ACSII码&#xff1f; 三、深度理解字符 - ‘0‘ 或者 ‘0‘ 四、实战演练 五、共勉 一、前言 想必大家在刷题或者是看别人写的代码中&#xff0c;经常会遇到 s[i]-’0‘ 或者 s[i]’0‘ 这个情况&#xff0c;初次遇到这种代码&#xff0c;肯定是…

【proverif】proverif的语法-各种密码原语的介绍和具体编码

proverif-系列文章目录 【proverif】proverif的下载安装和初使用【proverif】proverif的语法-解决中间人攻击-代码详解【proverif】proverif的语法2-各种密码原语的编码 &#xff08;本文&#xff09; 文章目录 proverif-系列文章目录前言铺垫知识一、对称加密二、非对称加密三…

java架构师禁止在项目中使用继承,合理吗?

java架构师禁止在项目中使用继承&#xff0c;合理吗&#xff1f; 如果建议用组合替代继承&#xff0c;非必要不用继承&#xff0c;这个很合理的建议的。 在非必要的情况下不用继承&#xff0c;用组合替代有几个优势&#xff1a;最近很多小伙伴找我&#xff0c;说想要一些 Jav…

音视频转换软件Permute mac中文板特点介绍

Permute mac是一款Mac平台上的媒体格式转换软件&#xff0c;由Chaotic Software开发。它可以帮助用户快速地将各种音频、视频和图像文件转换成所需格式&#xff0c;并提供了一些常用工具以便于用户进行编辑和处理。 Permute mac软件特点 - 支持大量格式&#xff1a;支持几乎所…

【强化学习】时间循环最优决策:原理与Python实战

Python 如何在时间循环里最优决策&#xff1f;时间旅行和平行宇宙时间旅行引发的悖论强化学习策略梯度算法代码案例代码推荐阅读理论完备&#xff1a;实战性强&#xff1a;配套丰富&#xff1a; 如何在时间循环里最优决策&#xff1f; 时间循环是一类热门的影视题材&#xff0…

Unity减少发布打包文件的体积(二)——设置WebGL发布时每张图片的压缩方式

一个项目在发布成WebGL后&#xff0c;其体积至关重要&#xff0c;体积太大&#xff0c;用户加载会经历一个漫长的等待…轻则骂娘&#xff0c;重则用脚把电脑踢烂(扣质保金)… 那么如何减少发布后的体积呢&#xff0c;本文从图片的压缩开始入手。 前传回顾&#xff1a; Unity减…

语雀 P0 事故复盘,这 9 个字亮了!

大家好&#xff0c;我是鱼皮。 最近语雀不是出了个号称 “载入史册” 的 P0 级事故嘛 —— 连续宕机 7 个多小时无法使用&#xff0c;作为一个大厂知名产品&#xff0c;这个修复速度属实让人无法理解。要命的是我们公司的知识库也是放在语雀上的&#xff0c;导致那天下午大家摸…

【C语法学习】26 - strcat()函数

文章目录 1 函数原型2 参数3 返回值4 使用说明5 示例5.1 示例1 1 函数原型 strcat()&#xff1a;将src指向的字符串拼接在dest指向的字符串末尾&#xff0c;函数原型如下&#xff1a; char *strcat(char *dest, const char *src);2 参数 strcat()函数有两个参数src和dest&am…

现货黄金休市时间长不长?科普一下交易时间

先告诉你答案&#xff0c;现货黄金市场每天的交易时间很长&#xff0c;因为它全天的盘面是由亚洲、欧洲和北美时间无缝地连接而成&#xff0c;无论投资者身处何方&#xff0c;通过哪里的平台入市&#xff0c;每天基本上都可以享受到连续20多个小时的行情。 只要投资者有足够的精…

如何下载到正确版本的Steam?正确使用实现多开搬砖不被封号

各位游戏玩家们&#xff0c;你们是否也曾因为无法在Steam平台上正常下载游戏而感到烦恼呢&#xff1f;盗版问题已经严重影响了Steam的用户体验&#xff0c;也给玩家们带来了不必要的经济损失。但是&#xff0c;作为玩家&#xff0c;我们需要更多的方法来区分正版和盗版&#xf…

【送书活动】阿里云经历的历史级的大故障,能给我们什么启迪?

作为一个淘系出来的人&#xff0c;参加过声势浩大的S11、S2大促&#xff1b;也和阿里云数据库团队、内核团队等并肩作战过&#xff1b;更是手握过六七百万的预算支持阿里云的服务&#xff0c;更是他们的至尊群用户&#xff0c;得知此次重大故障后&#xff0c;也甚是惊讶。 从阿…