Estos contenidos se han traducido de forma automática para su comodidad, pero Huawei Cloud no garantiza la exactitud de estos. Para consultar los contenidos originales, acceda a la versión en inglés.
Centro de ayuda/ GaussDB(DWS)/ Guía de gestión/ Conexión de clústeres/ Uso de la biblioteca de funciones de terceros psycopg2 de Python para conectarse a un clúster
Actualización más reciente 2024-06-12 GMT+08:00

Uso de la biblioteca de funciones de terceros psycopg2 de Python para conectarse a un clúster

Después de crear un clúster de almacén de datos y usar la biblioteca de funciones de terceros psycopg2 para conectarse al clúster, puede usar Python para acceder a GaussDB(DWS) y realizar varias operaciones en tablas de datos.

Preparativos antes de conectarse a un clúster

  • Se ha vinculado una EIP al clúster del almacén de datos.
  • Ha obtenido el nombre de usuario y la contraseña del administrador para iniciar sesión en la base de datos en el clúster del almacén de datos.
    Los algoritmos MD5 pueden ser vulnerables a ataques de colisión y no se pueden usar para la verificación de contraseñas. Actualmente, GaussDB(DWS) utiliza el diseño de seguridad predeterminado. De forma predeterminada, la verificación de contraseñas MD5 está deshabilitada y esto puede causar fallos en las conexiones de clientes de código abierto. Le aconsejamos que establezca password_encryption_type en 1. Para obtener más información, consulte Modificación de parámetros de base de datos.
    • Por motivos de seguridad, GaussDB(DWS) ya no usa MD5 para almacenar resúmenes de contraseñas de forma predeterminada. Como resultado, las unidades de código abierto y los clientes pueden no conectarse a la base de datos. Para utilizar el algoritmo MD5 utilizado en un protocolo de código abierto, debe modificar la política de contraseñas y crear un nuevo usuario, o cambiar la contraseña de un usuario existente.
    • La base de datos almacena el resumen hash de las contraseñas en lugar del texto de la contraseña. Durante la verificación de contraseña, el sistema compara el resumen de hash con el resumen de contraseña enviado desde el cliente (están involucradas las operaciones de sal). Si cambia la política de algoritmo criptográfico, la base de datos no puede generar un nuevo resumen hash para la contraseña existente. Para fines de conectividad, debe cambiar manualmente su contraseña o crear un nuevo usuario. La nueva contraseña se cifrará usando el algoritmo hash y se almacenará para la autenticación en la próxima conexión.
  • Ha obtenido la dirección de red pública, incluida la dirección de IP y el número de puerto en el clúster del almacén de datos. Para obtener más información, véase Obtención de la dirección de conexión de clúster.
  • Ha instalado la biblioteca de funciones de terceros psycopg2. Dirección de descarga: https://pypi.org/project/psycopg2/. Para obtener más información acerca de la instalación y el despliegue, consulte https://www.psycopg.org/install/.
    • En CentOS y Red Hat OS, ejecute el siguiente comando de yum:
      1
      yum install python-psycopg2
      
    • psycopg2 depende de la biblioteca dinámica libpq de PostgreSQL (versión de 32 bits o 64 bits, la que coincida con la versión de bits psycopg2). En Linux, puede ejecutar el comando yum y no necesita instalar la biblioteca. Antes de usar psycopg2 en Windows, debe instalar libpq de cualquiera de las siguientes maneras:
      • Instale PostgreSQL y configure las bibliotecas dinámicas libpq, ssl y crypto en la variable de entorno PATH.
      • Instale psqlodbc y utilice las bibliotecas dinámicas libpq, ssl y crypto que lleva el controlador ODBC de PostgreSQL.

Restricciones

psycopg2 es una interfaz de cliente basada en PostgreSQL, y sus funciones no son totalmente compatibles con GaussDB(DWS). Para obtener más información, véase Tabla 1.

Las siguientes API son compatibles basadas en Python 3.8.5 y psycopg 2.9.1.

Tabla 1 Las API de psycopg2 soportadas por DWS

Nombre de clase

Uso

Variable de función/miembro

Observaciones

connections

basic

cursor(name=None, cursor_factory=None, scrollable=None, withhold=False)

Y

-

commit()

Y

-

rollback()

Y

-

close()

Y

-

Two-phase commit support methods

xid(format_id, gtrid, bqual)

Y

-

tpc_begin(xid)

Y

-

tpc_prepare()

N

El núcleo no admite PREPARE TRANSACTION explícito.

tpc_commit([xid])

Y

-

tpc_rollback([xid])

Y

-

tpc_recover()

Y

-

closed

Y

-

cancel()

Y

-

reset()

N

DISCARD ALL no es compatible.

dsn

Y

-

Transaction control methods and attributes.

set_session(isolation_level=None, readonly=None, deferrable=None, autocommit=None)

Y

La base de datos no admite la configuración de default_transaction_read_only en una sesión.

autocommit

Y

-

isolation_level

Y

-

readonly

N

La base de datos no admite la configuración de default_transaction_read_only en una sesión.

deferrable

Y

-

set_isolation_level(level)

Y

-

encoding

Y

-

set_client_encoding(enc)

Y

-

notices

N

La base de datos no es compatible con listen/notify.

notifies

Y

-

cursor_factory

Y

-

info

Y

-

status

Y

-

lobject

N

La base de datos no admite operaciones relacionadas con objetos grandes.

Methods related to asynchronous support

poll()

Y

-

fileno()

Y

-

isexecuting()

Y

-

Interoperation with other C API modules

pgconn_ptr

Y

-

get_native_connection()

Y

-

informative methods of the native connection

get_transaction_status()

Y

-

protocol_version

Y

-

server_version

Y

-

get_backend_pid()

Y

El PID obtenido no es el PID de fondo, sino el ID de la conexión lógica.

get_parameter_status(parameter)

Y

-

get_dsn_parameters()

Y

-

cursor

basic

description

Y

-

close()

Y

-

closed

Y

-

connection

Y

-

name

Y

-

scrollable

N

La base de datos no es compatible con SCROLL CURSOR.

withhold

N

El withhold cursor debe cerrarse antes de la operación de confirmación.

Commands execution methods

execute(query, vars=None)

Y

-

executemany(query, vars_list)

Y

-

callproc(procname[, parameters])

Y

-

mogrify(operation[, parameters])

Y

-

setinputsizes(sizes)

Y

-

fetchone()

Y

-

fetchmany([size=cursor.arraysize])

Y

-

fetchall()

Y

-

scroll(value[, mode='relative'])

N

La base de datos no es compatible con SCROLL CURSOR.

arraysize

Y

-

itersize

Y

-

rowcount

Y

-

rownumber

Y

-

lastrowid

Y

-

query

Y

-

statusmessage

Y

-

cast(oid, s)

Y

-

tzinfo_factory

Y

-

nextset()

Y

-

setoutputsize(size[, column])

Y

-

COPY-related methods

copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None)

Y

-

copy_to(file, table, sep='\\t', null='\\\\N', columns=None)

Y

-

copy_expert(sql, file, size=8192)

Y

-

Interoperation with other C API modules

pgresult_ptr

Y

-

Uso de la biblioteca de funciones de terceros psycopg2 para conectarse a un clúster (Linux)

  1. Inicie sesión en el entorno de Linux como usuario root.
  2. Ejecute el siguiente comando para crear el archivo python_dws.py:

    vi python_dws.py

    Copie y pegue el siguiente contenido en el archivo python_dws.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    from __future__ import print_function
    import psycopg2
    def create_table(connection):
        print("Begin to create table")
        try:
            cursor = connection.cursor()
            cursor.execute("drop table if exists test;"
                           "create table test(id int, name text);")
            connection.commit()
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("Table created successfully")
            cursor.close()
    def insert_data(connection):
        print("Begin to insert data")
        try:
            cursor = connection.cursor()
            cursor.execute("insert into test values(1,'number1');")
            cursor.execute("insert into test values(2,'number2');")
            cursor.execute("insert into test values(3,'number3');")
            connection.commit()
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("Insert data successfully")
            cursor.close()
    def update_data(connection):
        print("Begin to update data")
        try:
            cursor = connection.cursor()
            cursor.execute("update test set name = 'numberupdated' where id=1;")
            connection.commit()
            print("Total number of rows updated :", cursor.rowcount)
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("After Update, Operation done successfully")
    def delete_data(connection):
        print("Begin to delete data")
        try:
            cursor = connection.cursor()
            cursor.execute("delete from test where id=3;")
            connection.commit()
            print("Total number of rows deleted :", cursor.rowcount)
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("After Delete,Operation done successfully")
    def select_data(connection):
        print("Begin to select data")
        try:
            cursor = connection.cursor()
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
            print("select failed")
        else:
            print("Operation done successfully")
            cursor.close()
    if __name__ == '__main__':
        try:
            conn = psycopg2.connect(host='10.154.70.231',
                                    port='8000',
                                    database='gaussdb',  # Database to be connected
                                    user='dbadmin',
                                    password='password')  # Database user password
        except psycopg2.DatabaseError as ex:
            print(ex)
            print("Connect database failed")
        else:
            print("Opened database successfully")
            create_table(conn)
            insert_data(conn)
            select_data(conn)
            update_data(conn)
            delete_data(conn)
            conn.close()
    

  3. Cambie la dirección de red pública, el número de puerto del clúster, el nombre de la base de datos, el nombre de usuario de la base de datos y la contraseña de la base de datos en el archivo python_dws.py basándose en la información real del clúster.

    La psycopg2 API no proporciona la capacidad de reintento de conexión. Es necesario implementar el procesamiento de reintentos en el código de servicio.

    1
    2
    3
    4
    5
            conn = psycopg2.connect(host='10.154.70.231',
                                    port='8000',
                                    database='gaussdb',  # Database to be connected
                                    user='dbadmin',
                                    password='password')  # Database user password
    

  4. Ejecute el siguiente comando para conectarse al clúster mediante la biblioteca de funciones de terceros psycopg:

    python python_dws.py

Uso de la biblioteca de funciones de terceros psycopg2 para conectarse a un clúster (Windows)

  1. En el sistema operativo Windows, haga clic en el botón Start, escriba cmd en el cuadro de búsqueda y haga clic en cmd.exe en la lista de resultados para abrir la interfaz de línea de comandos (CLI).
  2. En la CLI, ejecute el siguiente comando para crear el archivo python_dws.py:

    type nul> python_dws.py

    Copie y pegue el siguiente contenido en el archivo python_dws.py:

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    #!/usr/bin/python
    # -*- coding:UTF-8 -*-
    
    from __future__ import print_function
    
    import psycopg2
    
    
    def create_table(connection):
        print("Begin to create table")
        try:
            cursor = connection.cursor()
            cursor.execute("drop table if exists test;"
                           "create table test(id int, name text);")
            connection.commit()
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("Table created successfully")
            cursor.close()
    
    
    def insert_data(connection):
        print("Begin to insert data")
        try:
            cursor = connection.cursor()
            cursor.execute("insert into test values(1,'number1');")
            cursor.execute("insert into test values(2,'number2');")
            cursor.execute("insert into test values(3,'number3');")
            connection.commit()
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("Insert data successfully")
            cursor.close()
    
    
    def update_data(connection):
        print("Begin to update data")
        try:
            cursor = connection.cursor()
            cursor.execute("update test set name = 'numberupdated' where id=1;")
            connection.commit()
            print("Total number of rows updated :", cursor.rowcount)
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("After Update, Operation done successfully")
    
    
    def delete_data(connection):
        print("Begin to delete data")
        try:
            cursor = connection.cursor()
            cursor.execute("delete from test where id=3;")
            connection.commit()
            print("Total number of rows deleted :", cursor.rowcount)
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
        else:
            print("After Delete,Operation done successfully")
    
    
    def select_data(connection):
        print("Begin to select data")
        try:
            cursor = connection.cursor()
            cursor.execute("select * from test order by 1;")
            rows = cursor.fetchall()
            for row in rows:
                print("id = ", row[0])
                print("name = ", row[1], "\n")
        except psycopg2.ProgrammingError as e:
            print(e)
            print("select failed")
        else:
            print("Operation done successfully")
            cursor.close()
    
    
    if __name__ == '__main__':
        try:
            conn = psycopg2.connect(host='10.154.70.231',
                                    port='8000',
                                    database='postgresgaussdb',  # Database to be connected
                                    user='dbadmin',
                                    password='password')  # Database user password
        except psycopg2.DatabaseError as ex:
            print(ex)
            print("Connect database failed")
        else:
            print("Opened database successfully")
            create_table(conn)
            insert_data(conn)
            select_data(conn)
            update_data(conn)
            delete_data(conn)
            conn.close()
    

  3. Cambie la dirección de red pública, el número de puerto del clúster, el nombre de la base de datos, el nombre de usuario de la base de datos y la contraseña de la base de datos en el archivo python_dws.py basándose en la información real del clúster.

    1
    2
    3
    4
    5
            conn = psycopg2.connect(host='10.154.70.231',
                                    port='8000',
                                    database='gaussdb',  # Database to be connected
                                    user='dbadmin',
                                    password='password')  # Database user password
    

  4. En la CLI, ejecute el siguiente comando para usar psycopg para conectarse al clúster:

    python python_dws.py

¿Por qué no se admite el reintento de CN cuando psycopg2 está conectado a un clúster?

Con la función de reintento de CN, GaussDB(DWS) reintenta una sentencia que no se pudo ejecutar e identifica el tipo de error. Para obtener más información, consulte Reintento automático tras errores de ejecución de sentencias SQL. Sin embargo, en una sesión conectada usando psycopg2, una sentencia SQL fallida reportará un error y se detendrá para ser ejecutada. En una conmutación primaria/en espera, si no se vuelve a intentar una sentencia SQL fallida, se informará del siguiente error. Si la conmutación se completa durante un reintento automático, se devolverá el resultado correcto.

1
psycopg2.errors.ConnectionFailure: pooler: failed to create 1 connections, Error Message: remote node dn_6003_6004, detail: could not connect to server: Operation now in progress

Causas de error:

  1. psycopg2 envía la sentencia BEGIN para iniciar una transacción antes de enviar una sentencia SQL.
  2. El reintento de CN no admite sentencias en bloques de transacciones.

Solución:

  • En el modo de conexión sincrónica, finalice la transacción iniciada por el controlador.
    1
    2
    3
    4
    cursor = conn.cursor()
    # End the transaction started by the driver.
    cursor.execute("end; select * from test order by 1;") 
    rows = cursor.fetchall()
    
  • Iniciar una transacción en una conexión asincrónica. Para obtener más información, visite el sitio web oficial de PyScopg en: https://www.psycopg.org/docs/advanced.html?highlight=async
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #!/usr/bin/env python3
    # _*_ encoding=utf-8 _*_
    import psycopg2
    import select
    # Wait function provided by psycopg2 in asynchronous connection mode
    #For details, see https://www.psycopg.org/docs/advanced.html?highlight=async.
    def wait(conn):
        while True:
            state = conn.poll()
            if state == psycopg2.extensions.POLL_OK:
                break
            elif state == psycopg2.extensions.POLL_WRITE:
                select.select([], [conn.fileno()], [])
            elif state == psycopg2.extensions.POLL_READ:
                select.select([conn.fileno()], [], [])
            else:
                raise psycopg2.OperationalError("poll() returned %s" % state)
    def psycopg2_cnretry_sync():
        # Create a connection.
        conn = psycopg2.connect(host='10.154.70.231',
                                    port='8000',
                                    database='gaussdb',  # Database to be connected
                                    user='dbadmin',
                                    password='password',  # Database user password
                                    async=1) # Use the asynchronous connection mode.
        wait(conn)
        # Execute a query.
        cursor = conn.cursor()
        cursor.execute("select * from test order by 1;")
        wait(conn)
        rows = cursor.fetchall()
        for row in rows:
            print(row[0], row[1])
        # Close the connection.
        conn.close()
    if __name__ == '__main__':
        psycopg2_cnretry_async()