[PYTHON] Ich habe versucht, mit pypyodbc Preparation 1 schnell Daten von AS / 400 abzurufen

Im vorherigen Artikel Ich habe versucht, mit pypyodbc schnell Daten von AS / 400 abzurufen können Sie jetzt eine ODBC-Verbindung zu IBM i herstellen. Also habe ich mir viele Dinge ausgedacht, die ich tun wollte, aber als ich darüber nachdachte, musste ich sie vorbereiten, also habe ich dieses Mal dieses Gebiet geschaffen.

Der Grund, warum es "Nr. 1" ist, ist, dass es sich noch mitten auf der Straße befindet und nur der Eingabeteil verarbeitet werden kann. Die Ausgabe ist ohne die tatsächliche Maschine schwer zu überprüfen, daher ist sie diesmal vergangen.

Experimentierumgebung

Hilfsmodul

Ich denke, ich werde es später verbrauchen, also werde ich verschiedene Dinge in eine Datei (Modul) namens "sql_helper.py" packen. Es ist eine grundlegende Funktion, die Sie möglicherweise finden, wenn Sie nach einem Paket suchen, aber ich habe das Rad als Überprüfung von Python neu erfunden.

Es sieht vorerst so aus.

sql_helper.py


def _load_lines(filename, encoding='utf-8'):
    return [ l for l in open(filename, 'r', -1, encoding) ]


def load_raw_string(filename, encoding='utf-8', rstrip=True, lstrip=False):
    def _echo(x): return x

    if   (    rstrip  and      lstrip): func = str.strip
    elif (not rstrip  and      lstrip): func = str.lstrip
    elif (    rstrip  and  not lstrip): func = str.rstrip    # default
    else:                               func = _echo         # dummy

    if  rstrip: term = "\n"  # cause rstrip(None) is remove "\n"!
    else:       term = ""

    s = _load_lines(filename, encoding)
    return term.join( list(map(lambda x: func(x), s)) )


def load_sql(filename, encoding='utf-8', lstrip=False):
    sts = []
    for st in strip_comment( load_raw_string(filename, encoding, True, lstrip) ).split(";\n"):
        if (st.isspace()  or  st == "" ): continue
        sts.append(st.strip("; \t\n") )
    return sts


def load_config(filename, encoding='utf-8'):
    cf = {}
    for line in strip_comment(load_raw_string(filename, encoding)).split("\n"):
        if ( line == ""  or  line.isspace() ): continue
        key_, val_ = line.split("=")
        cf[ key_.strip() ] = val_.strip()
    return cf

# ...Wird etwas länger dauern...

Ich werde es kurz erklären.

_load_lines()

Lesen Sie die angegebene Datei. Erstellen Sie einfach eine Liste mit 1 Zeile, 1 Element und fertig. Ich möchte einfach nicht jedes Mal `open (xxx, ...). Readline ()` schreiben.

load_raw_string() Die mit _load_line () `erhaltene Liste wird gelesen, für jede Zeile mit lstrip () und rstrip () multipliziert und dann in eine einzelne Zeichenfolge rekonstruiert und zurückgegeben. Sollte ich auswählen können, ob die Leerzeichen am Zeilenanfang und die Leerzeichen am Zeilenende gelöscht werden sollen? Nach einer einfachen Entscheidung wurde der Code größer. Vor _load_lines () haben wir die Funktion hinzugefügt. (Es wird auch gesagt, dass ich die return-Anweisung in einer Zeile beenden möchte)

Funktion hängt vom Parameter ab, str.lstrip、str.rstrip、str.strip、_echo(Geben Sie einfach den Eingabewert zurück)Wird ersetzt.


 Wenn Sie str.rstrip und str.strip ohne Argumente aufrufen, verschwinden auch die Zeilenumbrüche am Ende der Zeile. Wird mit einer return-Anweisung eingegeben und rekonstruiert.

 load_sql()
 Holen Sie sich die SQL aus dem Dateinamen. Wenn ";" (+ Zeilenumbruch) darin enthalten ist, teilen Sie es dort und kehren Sie es in die Liste der SQL-Anweisungen zurück, und Sie sind fertig.

 Es war gut, bis ich dachte, aber um dies zu realisieren, machte ich Helfer für Helfer.
 Zum Beispiel wäre es schlecht, wenn es im Kommentar durch "; \ n" abgeschnitten würde, oder? Oder es wäre schlecht, wenn es durch das "; \ n" im Zitat abgeschnitten würde, oder? Oder so.
 Wenn es sich im zusammengesetzten Fall um `` `...; / * Blockkommentar * /` `handelt, stimmt es nicht mit"; \ n "überein, wenn Sie das Leerzeichen am Ende der Zeile nach dem Entfernen des Kommentars erneut entfernen müssen! Und so weiter....

 Was ich endlich mache, ist so
 1. Entfernen Sie Leerzeichen am Ende der Zeile mit load_row_string ()
 2. Entfernen Sie den Kommentar mit strip_comment () (später beschrieben) und entfernen Sie dann das Leerzeichen am Ende der Zeile, um den Kommentar zu entfernen.
 3. Teilen Sie zuletzt mit "; \ n" in eine einzelne SQL-Anweisung auf.
 4. Entfernen Sie das ";" selbst am Ende jedes Satzes
 5. 4. neu verpacken und zurücksenden

 Es wäre möglicherweise schneller gewesen, einen einfachen SQL-Analysator normal zu erstellen.


 load_config()
 Wenn Sie eine Datei im folgenden Format lesen ...


#### **`sample_connection.txt`**
```text

/* supports sql style comments */
  driver = {iSeries Access ODBC Driver}
    system = 127.0.0.1	
	uid    = USER01      
	pwd    = USER01   	

DefaultLibraries = MYLIB,TESTLIB1,TESTLIB2library

Konvertieren Sie in ein Wörterbuch wie dieses.

{'DefaultLibraries': 'MYLIB,TESTLIB1,TESTLIB2',
 'driver': '{iSeries Access ODBC Driver}',
 'pwd': 'USER01',
 'system': '127.0.0.1',
 'uid': 'USER01'}

Wenn Sie dieses Wörterbuch an die Funktion pypyodbc.connect () übergeben, müssen Sie keine Parameter hintereinander schreiben.

odbctest.py


from   pypyodbc import connect
import sql_helper as helper

config = helper.load_config( "sample_connection.txt" )

with connect( **config ) as connection:
    #Zugriffsverarbeitung auf Datenbank...

strip_comment() Wenn die Quelle länger wird, wird sie zu einer Funktion zum Entfernen von Kommentaren.

sql_helper.py


from  enum  import Enum, auto
class States(Enum):
    Statement = auto()
    Quoted    = auto()
    Comment   = auto()
    End       = auto()

_LimitLen = 999999999

def _singlequote_begin(s, b):
    p = s.find("'", b)
    return p   if (p >= 0) else _LimitLen

def _singlequote_end(s, b):
    p = s.find("'", b)
    if (p >= 0  and  p == s.find("''", b)):  p = _singlequote_end(s, p + 2)    # find recursive
    return (_next, p, 0, States.Statement)   if (p >= 0) else (None. _LimitLen, 0, States.End)

def _doublequote_begin(s, b):
    p = s.find('"', b)
    return p   if (p >= 0) else _LimitLen

def _doublequote_end(s, b):
    p = s.find('"', b)
    return (_next, p, 0, States.Statement)  if (p >= 0) else (None, _LimitLen, 0, States.End)

def _block_comment_begin(s, b):
    p = s.find("/*", b)
    return p + 1  if (p >= 0) else _LimitLen

def _block_comment_end (s, b):
    p = s.find("*/", b)
    return (_next, p + len("*/") - 1, len("*/") -1, States.Statement)  if (p >= 0) else (None, _LimitLen, 0, States.End)

def _line_comment_begin(s, b):
    p = s.find("--", b)
    return p + 1  if (p >= 0) else _LimitLen

def _line_comment_end(s, b):
    p =  s.find("\n", b)
    return (_next, p + len("\n") - 1, len("\n") - 1, States.Statement)   if (p >= 0) else (None, _LimitLen, 0, States.End)


def _quote_begin(s, b):
    next_state = States.Quoted
    sq, dq = _singlequote_begin(s, b), _doublequote_begin(s, b)
    if  (min(sq, dq) == _LimitLen): next_state = States.End
    return (_singlequote_end, sq, 0, next_state)  if (sq < dq) else (_doublequote_end, dq, 0, next_state)

def _comment_begin(s, b):
    bc, lc = _block_comment_begin(s, b), _line_comment_begin(s, b)
    if  (min(bc, lc) == _LimitLen): next_ = States.End
    return (_line_comment_end, lc, 0, States.Comment)    if (lc < bc) else  (_block_comment_end, bc, 0, States.Comment)

def _next(s, b):
    q_func, q_pos, q_ad, q_st = _quote_begin(s, b)
    c_func, c_pos, c_ad, c_st = _comment_begin(s, b)
    return  (q_func, q_pos, 0, q_st)  if (q_pos < c_pos) else (c_func, c_pos, 0, c_st)


def strip_comment( st ):
    #Kurze Bewertung
    if st == None  or  len( st.strip() ) == 0: return ""
    if ("/*" not in st)  and  ("--" not in st): return  "\n".join( list ( map(lambda x: x.rstrip(), st.split("\n"))))

    chars = list( st )

    comments = _find_comment_pos( st )
    comments.reverse()
    for c in comments:  del chars[ c[0]: c[1]]

    return "\n".join( list( map(lambda x: x.rstrip() , "".join( chars ).split("\n")) ) )


def _find_comment_pos( st ):
    cur   = -1
    begin =  0
    comments = []

    state = States.Statement
    pstate = None
    func = _next

    while (True):
        func, pos, adv, state = func(st, cur + 1)

        #Suche Ende
        if  ( state == States.End):
            if  (pstate == States.Comment):
                comments.append((begin, len(st)))
            break

        cur = pos

        #Beginnen Sie mit dem Kommentieren->Überspringen Sie die nachfolgende Verarbeitung
        if  (state == States.Quoted):
            pstate = state
            continue

        # end comment
        if  (pstate == States.Comment):
            comments.append((begin, pos + adv))
            pstate = state
            continue

        # begin comment
        if  (state == States.Comment):
            begin = pos - 1  # previous a length of single/double quotation

        pstate = state

    return comments

Ich erinnere mich nicht mehr an das, was ich geschrieben habe, deshalb erkläre ich es kurz.

Überblick

Strip_comment () und die Funktion, die die Kommentarposition durchsucht und eine Liste von (Startposition, Endposition) _find_comment_pos () zurückgibt. Die Hauptfunktionen sind die Funktionen und Objekte, die zuvor in einer Reihe angeordnet sind. Dies ist der von _find_comment_pos () verwendete Helfer. Die verschiedenen Funktionen wurden ursprünglich als interne Funktionen von _find_comment () definiert, aber auf diese Weise func, pos, adv, state = func(st, cur + 1) Wenn Sie ausführen, wird die erste Funktion(Die nächste zu suchende Funktion wird zurückgegeben)Es scheint jedoch, dass es sich nicht um ein normales Funktionsobjekt handelt, sondern um einen dreiteiligen Taple. Es scheint schwierig zu sein, herauszufinden, wie man damit umgeht, deshalb wechsle ich gehorsam zu einer normalen Funktion. (Aus diesem Grund habe ich beschlossen, zusätzliche Funktionen in das Modul zu streuen ...)

___find_comment___pos() Lokale Variablen'''func```Enthält die Funktion, die für die nächste Suche verwendet werden soll. Aktueller Status und Trefferzeichen("/**"Und"'"Und改行Und)Dies kann durch Teilen des Falls mit realisiert werden, aber da die bedingte Verzweigung schrecklich zu sein scheint, versuche ich, eine geeignete Suchfunktion entsprechend dem Treffercharakter zurückzugeben. Beispiel) "/"Wenn Sie finden, das nächste, wonach Sie suchen müssen"/"Da ist entschieden, die Funktion, danach zu suchen_block_comment_end()Ist entschieden

Reicht es zu diesem Zeitpunkt aus, die Trefferposition zusammen zurückzugeben? Ich dachte, aber nachdem ich diese Informationen haben möchte, brauche ich diese auch. Ich muss 4 Werte von jeder Funktion zurückgeben...。 Danach habe ich den numerischen Wert so angepasst, dass die Kommentarposition durch Slice angegeben werden kann, und sie in die Liste gepackt. (Ich habe die Details vergessen..)

strip_comment()

Nachdem die Position des Kommentars festgelegt wurde, müssen Sie den Kommentar nur noch mit einem Slice entfernen! !!

Die String-Klasse hat keine Methode, um das Zeichen an der Slice-Position zu entfernen! !!

Es kann nicht geholfen werdenchars = list( st )Konvertieren Sie in eine Liste von Zeichen mitdel chars[begin:end]Auf diese Weise gelang es mir schließlich, den Kommentar zu entfernen, nicht die lang erwartete Eissäge d.

Die letzte return-Anweisung, aber die leere Zeile am Ende der Zeile nach dem Entfernen des Kommentars("Text; /Kommentar/\n"Muster)Ich beschloss, erneut einen Kreisverkehr zu schreiben, um ihn weiter zu löschen.

#Schließlich Die für den Test verwendete Datei und der Testcode.(sample_connection.txt)Wird weggelassen, da es bereits gebucht wurde)

sample_multi_statement.sql


select * from SYSLIBL 
  where TYPE not like = "';%"   ;/* comment */

select * from SYSTABLES  ;   /* "" ' '' ; ;
" */

  ;  -- empty statement

select * from SYSCOLUMNS        ;
select * from SYSIBM.SYSDUMMY1;

strip_Zur Bestätigung der Kurzschlussauswertung des Kommentars

sample_multi_statement.sql


select * from SYSLIBL 
  where TYPE not like = "';%"   ;

select * from SYSTABLES  ;   

;

select * from SYSCOLUMNS        ;	
select * from SYSIBM.SYSDUMMY1;

sql_helper.py


def test_loading():
    from pprint import pprint

    file = "sample_multi_statement.sql"
    print( f'\ntest load_sql("{file}") ----------------------------')
    sts = load_sql( file )
    pprint( sts )

    file = "sample_multi_statement2.sql"
    print( f'\ntest load_sql("{file}") ----------------------------')
    sts = load_sql( file )
    pprint( sts )

    file = "sample_config.txt"
    print( f'\ntest load_config("{file}") ----------------------------')
    config = load_config( file )
    pprint( config )

Die Menge an Code war größer als erwartet, nur durch Lesen. Ich habe mit der Erstellung unter der Annahme begonnen, dass es mit IBM i verwendet wird, aber ich denke, dass der bisherige Inhalt als Vorverarbeitung für andere DBMS verwendet werden kann.

Nächstes Mal werden wir auf der Ausgabeseite beginnen.

Recommended Posts

Ich habe versucht, mit pypyodbc Preparation 1 schnell Daten von AS / 400 abzurufen
Ich habe versucht, mit pypyodbc schnell Daten von AS / 400 abzurufen
[Python] Ich habe versucht, mithilfe der YouTube-Daten-API verschiedene Informationen abzurufen!
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, mit AWS Lambda einen AMI zu erhalten
[Python] Ich habe versucht, den Typnamen als Zeichenfolge aus der Typfunktion abzurufen
Ich habe versucht, Daten aus einer Datei mit Node.js zu lesen.
Ich habe versucht, eine verdächtige Person mithilfe von Geolonia-Adressdaten schnell zu einem MAP zu machen
Ich möchte benutzerdefinierte Datenattribute von HTML als Elemente mit Python Selenium erhalten
Ich habe versucht, von Postman aus mit Cisco Guest Shell als API-Server zu arbeiten
Ich habe versucht, Videos mit der Youtube Data API (Anfänger) zu suchen.
Ich habe versucht, die Informationen des Webs mit "Requests" und "lxml" abzurufen.
Ich habe versucht, verschiedene Informationen von der Codeforces-API abzurufen
Holen Sie sich Daten von Twitter mit Tweepy
Ich habe versucht, mit Pandas eine Pferderenn-Datenbank zu erstellen
Ich habe versucht, den Index der Liste mithilfe der Aufzählungsfunktion abzurufen
Ich habe versucht, mit Boto3 eine Liste der AMI-Namen zu erhalten
Ich habe versucht, BigQuery-Daten mit Jupyter Lab mit GCP zu visualisieren
Ich habe versucht, Azure Speech to Text zu verwenden.
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich habe versucht, mit Hy anzufangen
Ich habe versucht, YOUTUBE Data API V3 zu verwenden
Ich habe versucht, Text mit TensorFlow zu klassifizieren
Ich habe versucht, die selektive Suche als R-CNN zu verwenden
Ich habe versucht, die UnityCloudBuild-API von Python zu verwenden
Ich habe versucht, Headless Chrome von Selenium zu verwenden
[Data Science-Grundlagen] Ich habe versucht, mit Python von CSV auf MySQL zu speichern
Ich habe versucht, die Trefferergebnisse von Hachinai mithilfe der Bildverarbeitung zu erhalten
Ich habe versucht, eine Clusteranalyse von Kunden anhand von Kaufdaten durchzuführen
Python-Programmierung: Ich habe versucht, mithilfe von BeautifulSoup4 Unternehmensinformationen (Crawlen) von Yahoo Finance in den USA abzurufen
Ich habe versucht, durch Schaben ein Bild zu bekommen
Ich habe versucht, die Daten mit Zwietracht zu speichern
Ich möchte mit Python eine E-Mail von Google Mail senden.
Ich habe versucht, mit OpenCV Bewegungen schnell zu erkennen
Ich habe versucht, WAV-Dateien mit Pydub zu synthetisieren.
So erhalten Sie Artikeldaten mithilfe der Qiita-API
Ich möchte die Daten von League of Legends ③ erhalten
Ich möchte die Daten von League of Legends ② erhalten
Ich möchte League of Legends-Daten erhalten ①
Ich habe DBM mit Pylearn 2 unter Verwendung künstlicher Daten ausprobiert
Ich habe ein ○ ✕ Spiel mit TensorFlow gemacht
Ich habe versucht, die multiple Regressionsanalyse anhand konkreter Beispiele so einfach wie möglich zu erklären.
Python-Programmierung: Ich habe versucht, Nachrichtenartikel mit Selenium und BeautifulSoup4 abzurufen (zu crawlen)
Ich habe versucht, Python-Code aus .Net mit Pythonnet auszuführen (Hallo World Edition)
Ich habe versucht, die Informationen der ASPX-Site, die mit Selenium IDE ausgelagert wird, so programmlos wie möglich abzurufen
Ich habe versucht, parametrisiert zu verwenden
Ich habe versucht, Mimesis zu verwenden
Ich habe versucht, anytree zu verwenden
Ich habe versucht, aiomysql zu verwenden
Ich habe versucht, mit Blenders Python script_Part 01 zu beginnen
Ich habe versucht, Summpy zu verwenden
Ich habe versucht, das Spiel in der J League vorherzusagen (Datenanalyse)
Ich habe versucht, Pferderennen vorherzusagen, indem ich alles von der Datenerfassung bis zum tiefen Lernen getan habe
Ich habe versucht, Coturn zu verwenden
Ich habe versucht, Pipenv zu verwenden
Ich habe versucht, Matplotlib zu verwenden
Ich habe versucht, "Anvil" zu verwenden.
Ich habe versucht, Hubot zu verwenden
Ich habe versucht, ESPCN zu verwenden