"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > पायथन का उपयोग करके ओडीबीसी या जेडीबीसी के साथ आईआरआईएस डेटाबेस तक पहुंचें

पायथन का उपयोग करके ओडीबीसी या जेडीबीसी के साथ आईआरआईएस डेटाबेस तक पहुंचें

2024-11-15 को प्रकाशित
ब्राउज़ करें:706

Access IRIS database with ODBC or JDBC using Python

स्ट्रिंग्स के साथ समस्याएँ

मैं पायथन का उपयोग करके जेडीबीसी (या ओडीबीसी) के साथ आईआरआईएस डेटाबेस तक पहुंच रहा हूं। मैं डेटा में हेरफेर करने और उससे चार्ट बनाने के लिए डेटा को pandas डेटाफ़्रेम में लाना चाहता हूं। जेडीबीसी का उपयोग करते समय मुझे स्ट्रिंग हैंडलिंग में समस्या का सामना करना पड़ा। यदि किसी और को भी यही समस्या है तो यह पोस्ट मदद के लिए है। या, यदि इसे हल करने का कोई आसान तरीका है, तो मुझे टिप्पणियों में बताएं!

मैं ओएसएक्स का उपयोग कर रहा हूं, इसलिए मैं अनिश्चित हूं कि मेरी समस्या कितनी अनोखी है। मैं ज्यूपिटर नोटबुक का उपयोग कर रहा हूं, हालांकि यदि आप किसी अन्य पायथन प्रोग्राम या फ्रेमवर्क का उपयोग करते हैं तो कोड आम तौर पर वही होगा।

जेडीबीसी समस्या

जब मैं डेटाबेस से डेटा लाता हूं तो कॉलम विवरण और कोई भी स्ट्रिंग डेटा डेटा प्रकार java.lang.String के रूप में लौटाया जाता है। यदि आप स्ट्रिंग डेटा डेटा प्रिंट करते हैं तो यह अपेक्षित "दर्दनाक" के बजाय इस तरह दिखेगा: "(p,a,i,n,i,n,t,h,e,r,e,a,r)"।

ऐसा शायद इसलिए है क्योंकि JDBC का उपयोग करके लाए जाने पर डेटा प्रकार java.lang.String के कैरेक्टर स्ट्रिंग एक पुनरावर्तनीय या सरणी के रूप में आ रहे हैं। ऐसा तब हो सकता है जब आप जिस Python-Java ब्रिज का उपयोग कर रहे हैं (उदाहरण के लिए, JayDeBeApi, JDBC) एक ही चरण में java.lang.String को Python str में स्वचालित रूप से परिवर्तित नहीं कर रहा है।

पायथन की स्ट्रिंग स्ट्रिंग प्रस्तुति, इसके विपरीत, पूरी स्ट्रिंग को एक इकाई के रूप में रखती है। जब पायथन एक सामान्य str पुनर्प्राप्त करता है (उदाहरण के लिए ODBC के माध्यम से), तो यह अलग-अलग वर्णों में विभाजित नहीं होता है।

जेडीबीसी समाधान

इस समस्या को ठीक करने के लिए, आपको यह सुनिश्चित करना होगा कि java.lang.String सही ढंग से पायथन के str प्रकार में परिवर्तित हो गया है। प्राप्त डेटा को संसाधित करते समय आप इस रूपांतरण को स्पष्ट रूप से संभाल सकते हैं ताकि इसे पुनरावर्तनीय या वर्णों की सूची के रूप में व्याख्या न किया जाए।

इस स्ट्रिंग हेरफेर को करने के कई तरीके हैं; यह जो मैंने किया है।

import pandas as pd

import pyodbc

import jaydebeapi
import jpype

def my_function(jdbc_used)

    # Some other code to create the connection goes here

    cursor.execute(query_string)

    if jdbc_used:
        # Fetch the results, convert java.lang.String in the data to Python str
        # (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,r,e,a,r)" Convert to str type "painintherear"
        results = []
        for row in cursor.fetchall():
            converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row]
            results.append(converted_row)

        # Get the column names and ensure they are Python strings 
        column_names = [str(col[0]) for col in cursor.description]

        # Create the dataframe
        df = pd.DataFrame.from_records(results, columns=column_names)

        # Check the results
        print(df.head().to_string())

    else:  
        # I was also testing ODBC
        # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall()
        results = cursor.fetchall()
        # Get the column names
        column_names = [column[0] for column in cursor.description]
        # Create the dataframe
        df = pd.DataFrame.from_records(results, columns=column_names)

    # Do stuff with your dataframe

ओडीबीसी समस्या

ODBC कनेक्शन का उपयोग करते समय, स्ट्रिंग वापस नहीं आती हैं या NA होती हैं।

यदि आप किसी ऐसे डेटाबेस से कनेक्ट कर रहे हैं जिसमें यूनिकोड डेटा है (उदाहरण के लिए, विभिन्न भाषाओं में नाम) या यदि आपके एप्लिकेशन को गैर-एएससीआईआई वर्णों को संग्रहीत या पुनर्प्राप्त करने की आवश्यकता है, तो आपको यह सुनिश्चित करना होगा कि डेटा के बीच पारित होने पर डेटा सही ढंग से एन्कोड किया गया हो डेटाबेस और आपका पायथन एप्लिकेशन।

ओडीबीसी समाधान

यह कोड सुनिश्चित करता है कि डेटाबेस में डेटा भेजते और पुनर्प्राप्त करते समय स्ट्रिंग डेटा को UTF-8 का उपयोग करके एन्कोड और डिकोड किया जाता है। गैर-ASCII वर्णों से निपटने या यूनिकोड डेटा के साथ संगतता सुनिश्चित करते समय यह विशेष रूप से महत्वपूर्ण है।

def create_connection(connection_string, password):
    connection = None

    try:
        # print(f"Connecting to {connection_string}")
        connection = pyodbc.connect(connection_string   ";PWD="   password)

        # Ensure strings are read correctly
        connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8")
        connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8")
        connection.setencoding(encoding="utf8")

    except pyodbc.Error as e:
        print(f"The error '{e}' occurred")

    return connection

connection.setdecoding(pyodbc.SQL_CHAR, encoding='utf8'')

pyodbc को बताता है कि SQL_CHAR प्रकार (आमतौर पर, निश्चित-लंबाई वर्ण फ़ील्ड) लाते समय डेटाबेस से कैरेक्टर डेटा को कैसे डीकोड किया जाए।

connection.setdecoding(pyodbc.SQL_WCHAR, encoding='utf8'')

SQL_WCHAR, विस्तृत-वर्ण प्रकार (यानी, यूनिकोड स्ट्रिंग्स, जैसे SQL सर्वर में NVARCHAR या NCHAR) के लिए डिकोडिंग सेट करता है।

connection.setencoding(encoding='utf8''

यह सुनिश्चित करता है कि पायथन से डेटाबेस में भेजे गए किसी भी स्ट्रिंग या कैरेक्टर डेटा को UTF-8 का उपयोग करके एन्कोड किया जाएगा,
जिसका अर्थ है कि डेटाबेस के साथ संचार करते समय पायथन अपने आंतरिक str प्रकार (जो यूनिकोड है) को UTF-8 बाइट्स में अनुवादित करेगा।


यह सब एक साथ रखना

जेडीबीसी स्थापित करें

JAVA स्थापित करें - dmg का उपयोग करें

https://www.oracle.com/middleeast/java/technologies/downloads/#jdk23-mac

डिफ़ॉल्ट संस्करण सेट करने के लिए शेल को अपडेट करें

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    23 (arm64) "Oracle Corporation" - "Java SE 23" /Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home
    1.8.421.09 (arm64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home
$ echo $SHELL
/opt/homebrew/bin/bash
$ vi ~/.bash_profile

अपने पथ में JAVA_HOME जोड़ें

export JAVA_HOME=$(/usr/libexec/java_home -v 23)
export PATH=$JAVA_HOME/bin:$PATH

जेडीबीसी ड्राइवर प्राप्त करें

https://intersystems-community.github.io/iris-driver-distribution/

जार फ़ाइल को कहीं रखें... मैंने इसे $HOME में रखा है

$ ls $HOME/*.jar
/Users/myname/intersystems-jdbc-3.8.4.jar

नमूना कोड

यह मान लिया गया है कि आपने ओडीबीसी स्थापित कर लिया है (किसी अन्य दिन के लिए एक उदाहरण, कुत्ते ने मेरे नोट्स खा लिए...)।

नोट: यह मेरे वास्तविक कोड का हैक है। चर नामों पर ध्यान दें।

import os

import datetime
from datetime import date, time, datetime, timedelta

import pandas as pd
import pyodbc

import jaydebeapi
import jpype

def jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password):

    # Path to JDBC driver
    jdbc_driver_path = '/Users/yourname/intersystems-jdbc-3.8.4.jar'

    # Ensure JAVA_HOME is set
    os.environ['JAVA_HOME']='/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home'
    os.environ['CLASSPATH'] = jdbc_driver_path

    # Start the JVM (if not already running)
    if not jpype.isJVMStarted():
        jpype.startJVM(jpype.getDefaultJVMPath(), classpath=[jdbc_driver_path])

    # Connect to the database
    connection = None

    try:
        connection = jaydebeapi.connect("com.intersystems.jdbc.IRISDriver",
                                  jdbc_url,
                                  [jdbc_username, jdbc_password],
                                  jdbc_driver_path)
        print("Connection successful")
    except Exception as e:
        print(f"An error occurred: {e}")

    return connection


def odbc_create_connection(connection_string):
    connection = None

    try:
        # print(f"Connecting to {connection_string}")
        connection = pyodbc.connect(connection_string)

        # Ensure strings are read correctly
        connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8")
        connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8")
        connection.setencoding(encoding="utf8")

    except pyodbc.Error as e:
        print(f"The error '{e}' occurred")

    return connection

# Parameters

odbc_driver = "InterSystems ODBC"
odbc_host = "your_host"
odbc_port = "51773"
odbc_namespace = "your_namespace"
odbc_username = "username"
odbc_password = "password"

jdbc_host = "your_host"
jdbc_port = "51773"
jdbc_namespace = "your_namespace"
jdbc_username = "username"
jdbc_password = "password"

# Create connection and create charts

jdbc_used = True

if jdbc_used:
    print("Using JDBC")
    jdbc_url = f"jdbc:IRIS://{jdbc_host}:{jdbc_port}/{jdbc_namespace}?useUnicode=true&characterEncoding=UTF-8"
    connection = jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password)
else:
    print("Using ODBC")
    connection_string = f"Driver={odbc_driver};Host={odbc_host};Port={odbc_port};Database={odbc_namespace};UID={odbc_username};PWD={odbc_password}"
    connection = odbc_create_connection(connection_string)


if connection is None:
    print("Unable to connect to IRIS")
    exit()

cursor = connection.cursor()

site = "SAMPLE"
table_name = "your.TableNAME"

desired_columns = [
    "RunDate",
    "ActiveUsersCount",
    "EpisodeCountEmergency",
    "EpisodeCountInpatient",
    "EpisodeCountOutpatient",
    "EpisodeCountTotal",
    "AppointmentCount",
    "PrintCountTotal",
    "site",
]

# Construct the column selection part of the query
column_selection = ", ".join(desired_columns)

query_string = f"SELECT {column_selection} FROM {table_name} WHERE Site = '{site}'"

print(query_string)
cursor.execute(query_string)

if jdbc_used:
    # Fetch the results
    results = []
    for row in cursor.fetchall():
        converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row]
        results.append(converted_row)

    # Get the column names and ensure they are Python strings (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,a,r,s,e)"
    column_names = [str(col[0]) for col in cursor.description]

    # Create the dataframe
    df = pd.DataFrame.from_records(results, columns=column_names)
    print(df.head().to_string())
else:
    # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall()
    results = cursor.fetchall()
    # Get the column names
    column_names = [column[0] for column in cursor.description]
    # Create the dataframe
    df = pd.DataFrame.from_records(results, columns=column_names)

    print(df.head().to_string())

# # Build charts for a site
# cf.build_7_day_rolling_average_chart(site, cursor, jdbc_used)

cursor.close()
connection.close()

# Shutdown the JVM (if you started it)
# jpype.shutdownJVM()
विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/intersystems/access-iris-database-with-odbc-or-jdbc-using-python-54ok?1 यदि कोई उल्लंघन है, तो कृपया [email protected] से संपर्क करें। इसे हटाने के लिए
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3