es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Python: subprocess + isql en Windows: se requiere un objeto tipo bytes, no ‘str’

Este es un ordenador proporcionado por la empresa y no puedo instalar ningún nuevo software en él. Sin embargo, puedo instalar módulos de Python en mi propio directorio. Necesito ejecutar algo en Sybase y hay más de 10 servidores. La operación manual consume mucho tiempo, por lo tanto, estoy buscando la opción de utilizar Python + subprocess.

Realicé algunas investigaciones y consulté https://stackoverflow.com/questions/25035026/using-subprocess-module-in-python-to-run-isql-command. Sin embargo, mi versión no funciona. El mensaje de error es TypeError: se requiere un objeto similar a bytes, no ‘str’. Este mensaje de error apareció en la línea “communicate”.

Puedo ver que mi “isql” se ha conectado correctamente porque obtengo una isql.pid.

¿Me he perdido algo aquí?

Gracias

import subprocess
from subprocess import Popen, PIPE
import keyring
from textwrap import dedent

server = "MYDB"
cmd = r"C:\Sybase15\OCS-15<em>0\bin\isql.exe"
interface = r"C:\Sybase15\ini\sql.ini"
c = keyring.get</em>credential("db", None)
username = c.username
password = c.password

isql = Popen([cmd, '-I', interface,
              '-S', server,
              '-U', username, 
              '-P', password,
              '-w', '99999'], stdin=PIPE, stdout=PIPE)
output = isql.communicate("""\
    SET NOCOUNT ON
    {}
    go
""".format("select count(*) from syslogins"))[0]
Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece que el mensaje de error es causado por el hecho de que Python 3.x requiere objetos similares a bytes al utilizar los argumentos stdin y stdout con el método subprocess.communicate(). Una posible solución es codificar la cadena de entrada utilizando el método encode() antes de pasarla a communicate(). A continuación se muestra un fragmento de código actualizado que debería funcionar:

    import subprocess
    from subprocess import Popen, PIPE
    import keyring
    from textwrap import dedent
    
    server = "MYDB"
    cmd = r"C:\Sybase15\OCS-15_0\bin\isql.exe"
    interface = r"C:\Sybase15\ini\sql.ini"
    c = keyring.get_credential("db", None)
    username = c.username
    password = c.password
    
    query = dedent('''
        SET NOCOUNT ON
        {}
        go
    '''.format('select count(*) from syslogins'))
    
    isql = Popen([cmd, '-I', interface, '-S', server, '-U', username, '-P', password, '-w', '99999'], stdin=PIPE, stdout=PIPE)
    output = isql.communicate(query.encode())[0]
    
    print(output.decode())
    

    La función dedent() se utiliza para eliminar los espacios en blanco iniciales de la cadena de entrada, asegurando que la consulta esté correctamente formateada. El método encode() se utiliza para convertir la cadena en bytes antes de pasarla a communicate(). Por último, el método decode() se utiliza para convertir los bytes de salida nuevamente en una cadena para su impresión.

Comments are closed.