Muszę wyodrębnić dużą ilość danych z bazy danych HP Vertica i zapisać go do pliku. Używam oficjalnego sterownika ODBC z Vertica z Pyodbc.

Oto, co zrobiłem do tej pory:

cnxn = pyodbc.connect('DRIVER={Vertica};SERVER=localhost;DATABASE=db;UID=user;PWD=pw')
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
cnxn.setencoding(str, encoding='utf-8')
cnxn.setencoding(unicode, encoding='utf-8')
cur = cnxn.cursor()
cur.execute("SELECT * FROM schema.table LIMIT 3")

Potem przeczytałem dane

for row in cur:
    print row

Większość pól jest zwracana po prostu dobrze - Tekst Unicode, Liczby lub DateTimes. Jednak dla pola przechowuje adresy IP, otrzymuję:

bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\\')

Jak konwertować go na tekst?

Każda pomoc w znacznym stopniu doceniana!

Dzięki!

2
Mikhail Venkov 28 wrzesień 2017, 20:50

2 odpowiedzi

Najlepsza odpowiedź

Widzę, że jest akceptowana odpowiedź, ale ... dla wszystkich innych:

Jeśli Twoje dane znajdują się w Vercica bardzo , aby zrobić to, aby sprawdzić dokładną instrukcję obsługi SQL. W tym przypadku znajdziesz wbudowaną funkcję do konwersji adresu IPv6 reprezentowanego jako kolumna Warbinary do łańcucha.

Znacznie prostsze i wiele szybciej:

SELECT V6_NTOA(your_column_here) ;
3
mauro 30 wrzesień 2017, 04:02

Wairbinary (16) to 128 bitów, co jest odpowiednim rozmiarem dla adresu IPv6. Próbki dekoduje dane

0000:0000:0000:0000:0000:ffff:0a6f:195c

Oraz "adresowane adresy IPv6 IPv6 IPv6" podsekcja artykułu Wikipedii na IPv6 (ref: Tutaj ) mówi, że taki adres jest adresem IPv4 (32 bitów) mapowany w formacie IPv6 (128 bitów).

::ffff:10.111.25.92

Możemy generować te reprezentacje strunowe powyżej z danych RAW {X0}} za pomocą takiego funkcji:

def bytes_to_ip_address(byte_array):
    if byte_array[0:12] == bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff'):
        return '{0}.{1}.{2}.{3}'.format(byte_array[12], byte_array[13], byte_array[14], byte_array[15])
    else:
        return ':'.join(['{0:02x}{1:02x}'.format(byte_array[i], byte_array[i + 1]) for i in range(0, len(byte_array), 2)])


if __name__ == '__main__':
    # examples
    fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\\')
    print(bytes_to_ip_address(fld))  # 10.111.25.92
    fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\\')
    print(bytes_to_ip_address(fld))  # 0100:0000:0000:0000:0000:ffff:0a6f:195c

Lub, z python3, możemy użyć Ipaddress moduł:

import ipaddress


def bytes_to_ip_address(byte_array):
    ip6 = ipaddress.IPv6Address(bytes(byte_array))
    ip4 = ip6.ipv4_mapped
    if ip4 == None:
        return str(ip6)
    else:
        return str(ip4)


if __name__ == '__main__':
    # examples
    fld = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\\')
    print(bytes_to_ip_address(fld))  # 10.111.25.92
    fld = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\no\x19\\')
    print(bytes_to_ip_address(fld))  # 100::ffff:a6f:195c
1
Gord Thompson 29 wrzesień 2017, 23:26