Προς το περιεχόμενο

Python suds response


Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

Δεν είμαι καθόλου έμπειρος με προγραμματισμό και python οπότε μη βαρατε αν λέω χαζομάρες.

 

Χρησιμοποιώ python και το suds για SOAP queries. Κάνω query σε έναν soap server (με το αντίστοιχο wsdl και xsd) αλλά η απάντηση που παίρνω δεν είναι καλά formatted. Το query είναι για μια database.

 

Yποτίθεται ότι το suds το φορμάρει κατάλληλα με βάση το xsd αρχείο

Το query είναι απλό πχ

 

select * from tableclass

 

H απάντηση που παίρνω είναι η παρακάτω

 

print(result)

 

(reply){
   return =
      (return){
         row[] =
            (anyType){
               enum = "1"
               name = "Phone"
               moniker = "CLASS_PHONE"
            },
            (anyType){
               enum = "2"
               name = "Gateway"
               moniker = "CLASS_GATEWAY"
            },
            (anyType){
               enum = "4"
               name = "Conference Bridge"
               moniker = "CLASS_CONF_BRIDGE"
            },
            (anyType){
               enum = "5"
               name = "Media Termination Point"
               moniker = "CLASS_MTP"

 

etc etc etc

 

Κάθε ζεύγος (enum, name, moniker) είναι και μια γραμμή και αυτά τα τρία είναι οι στήλες, ενώ στο παραπάνω είναι όλα σε μια γραμμή ή έτσι νομίζω εγώ τουλάχιστον.

 

Aν κάνω print το παρακάτω

 

print(result[0]['row'][1])

 

παίρνω αυτό:

(anyType){
   enum = "2"
   name = "Gateway"
   moniker = "CLASS_GATEWAY"
 }

 

Πώς γίνεται να τα γράψω σε αρχείο και να φαίνονται ωραία όπως για παράδειγμα

 

tableclass

 

enum                   name               moniker

=======             ======            ========

1                        Phone               CLASS_PHONE

 

ή ακόμα καλύτερα αν είναι comma delimited ώστε να μπορώ να τα κάνω import στο excel πχ

 

Αν θέλετε μπορώ να δώσω περισσότερες λεπτομέρειες

 

Ευχαριστώ

Επεξ/σία από beastgr
Δημοσ.
import csv

def write_to_csv(rows, filename='query_out.csv'):
    with open(filename, 'wb') as fd:
        writer = csv.writer(fd)
        for row in rows:
            writer.writerow(row.values())


def do_query():
    pass


def main():
    result = do_query()
    write_to_csv(result[0]['row'])

if __name__ == '__main__':
    main()

Δεν θα επρεπε να σε μπερδευει νομιζω..

Δημοσ.

Ευχαριστώ! Για κάποιον που άρχισε να ασχολείται με προγραμματισμό (και δη με python) πριν κανα μήνα μια χαρά μπερδεύομαι :)

Αλλά σιγά σιγά το προχωράω όσο μπορώ. Το πρόγραμμά σου μου βγάζει λάθος όταν το τρέχω

 

Traceback (most recent call last):
  File "C:\Python34\apps\test_axl_local_wsdl.py", line 61, in <module>
    write_to_csv(result[0]['row'])
  File "C:\Python34\apps\test_axl_local_wsdl.py", line 21, in write_to_csv
    writer.writerow(row.values())
AttributeError: 'anyType' object has no attribute 'values'

 

Υποπτεύμαι ότι το πρόβλημα είναι στη μέθοδο values η οποία τρέχει μόνο σε dictionaries ενώ δεν έχω κανένα dictionary defined.

 

Εγώ το πήγαινα αλλιώς παντως. Έχω βάλει όλεις τις values σε nested lists (μια list που περιέχει πολλές μικρότερες με 3 values ανα list μιας και έχω 3 columns) και τώρα προσπαθώ να τις κάνω split ώστε να τις γράψω σε ένα αρχείο. Μάλλον θα υπάρχει πιο ευκολος τρόπος απλά δεν έχω ακομα τις ικανότητες να τον βρω

Δημοσ.

warchief o κώδικας που μου έδωσες βοήθησε. Τελικά τα κατάφερα χρησιμοποιώντας το csv module (που δεν το ήξερα είναι η αλήθεια) και με πολύ trial&error τα κατάφερα

 

Όπως είπα ο κώδικας μου σίγουρα δε θα είναι ο βέλτιστος ίσα ίσα χάλια μάλλον είναι αλλά στο στάδιο που βρίσκομαι, είμαι χαρούμενος που απλά δουλεύει :)

Δημοσ.

warchief o κώδικας που μου έδωσες βοήθησε. Τελικά τα κατάφερα χρησιμοποιώντας το csv module (που δεν το ήξερα είναι η αλήθεια) και με πολύ trial&error τα κατάφερα

 

Όπως είπα ο κώδικας μου σίγουρα δε θα είναι ο βέλτιστος ίσα ίσα χάλια μάλλον είναι αλλά στο στάδιο που βρίσκομαι, είμαι χαρούμενος που απλά δουλεύει :)

 

Assumptions is the mother of all evil.. :-)

Οπως εδωσες το φορμαρισμενο print του result και επειδή ειχε αγκυλες {} με key, value pairs υπεθεσα πως το καθε row το κανει wrap σαν python dictionary..

 

Κανε paste του κωδικα που εχεις να δουμε αν μπορει να γινει καλυτερα.

Δημοσ.

Εγώ να δεις πόσο χρόνο μου πήρε να βρω πως θα έχω πρόσβαση στα contents. Γι αυτό μου φάνηκε ότι το suds δεν έκανε και τόσο καλά parse την απάντηση του soap server.

 

Σε ευχαριστώ που θέλεις να ρίξεις μια ματιά στον κώδικα. Απλά να ξέρεις ότι επειδή άρχισα να ασολούμαι πριν κανα 3 βδομάδες με προγραμματισμό μπορεί να μην καταλαβαίνω τα comments σου. Αν μπορείς να χρησιμοποιείς απλά παραδείγματα θα ήταν τέλεια!

 

Ευχαριστώ για το χρόνο σου!

 

 

 

import tkinter as tk
from tkinter import W,E

from suds.client import Client
from suds.cache import ObjectCache
import logging

import requests
from requests.auth import HTTPBasicAuth

import csv

# LoginApp will be used to generate the login window and authenticate the user
class LoginApp(tk.Frame):
    
    def __init__(self,parent):
        tk.Frame.__init__(self, parent)
        #hide the main root window until we authenticate
        root.withdraw()
        self.parent = parent
        self.login_frame = tk.Frame(self.parent, width=1000, height=100)
        self.ipaddress = tk.Label(self.login_frame, text="IP Address:")
        self.username = tk.Label(self.login_frame, text="Username:")
        self.password = tk.Label(self.login_frame, text="Password:")
        self.textip = tk.Entry(self.login_frame)
        LoginApp.textuser = tk.Entry(self.login_frame) # I prepend the class name because I need to use the variable outside this class (it is a class variable)
        LoginApp.textpass = tk.Entry(self.login_frame,show="*") #hides the password while typing
        # The CONNECT button will execute the validate_connection function
        self.connect = tk.Button(self.login_frame, text="CONNECT", command=self.validate_connection)
        # I need to bind the whole root1 window if I want to invoke the validate_connection function by pressing enter
        root1.bind('<Return>', self.validate_connection)
        self.cancel = tk.Button(self.login_frame, text="CANCEL")

        # the following line use the grid geometry manager to put every widget to a designated place within the frame
        self.login_frame.grid(column=0, row=0)
        self.ipaddress.grid(column=0,row=0,sticky=W)
        self.username.grid(column=0,row=1,sticky=W)
        self.password.grid(column=0,row=2,sticky=W)
        self.textip.grid(column=1,row=0)
        self.textuser.grid(column=1,row=1)
        self.textpass.grid(column=1,row=2)
        self.connect.grid(column=0,row=3, sticky=W+E)
        self.cancel.grid(column=1,row=3)


    # with this function we will connect to the ip address provided and will check the credentials against CUCM
    # I also need to add the *args because the root1.bind() command on the __init__ function needs one argument. Same could be accomplished using a lambda on the
    # root1.bind command
    def validate_connection(self, *args):
        print("Ip address is %s, the username is %s and the pass is %s" %(self.textip.get(), self.textuser.get(), self.textpass.get())) # just a test print to see if we get the correct values

        # building the url of cucm based on userinput
        LoginApp.location= 'https://'+self.textip.get()+'/axl/'

        #connecting to the axl web page of cucm using the provided credentials. SSL verification is set to false (not recommended)
        r=requests.get(LoginApp.location,auth=HTTPBasicAuth(self.textuser.get(),self.textpass.get()),verify=False)

        #if authentication is successful we will call the auth_succ function otherwise we call the auth_unsucc function
        if r.status_code == 200 :
            print('Authentication successful')
            #self.login_frame.destroy()
            self.parent.withdraw()
            self.auth_succ()
        else:
            print('Authentication not successful')
            self.login_frame.destroy()
            self.auth_unsucc()

    #this function will create a new window just to say that authentication is successful and once the button OK is pressed the gotoMainapp function will be executed
    #the new window is on top of root window and we use the toplevel function 
    def auth_succ(self):
        print("success")
        self.success_dlg=tk.Toplevel(self.parent,width=1000, height=100)
        self.success=tk.Label(self.success_dlg, text="Authentication successful")
        self.ok=tk.Button(self.success_dlg, text="OK", command=self.gotoMainapp)
        self.success.grid(column=0,row=0)
        self.ok.grid(column=0, row=1)
        root1.bind('<Return>', self.gotoMainapp)
        #root.deiconify()
    def auth_unsucc(self):
        print("failure")
        self.unsucc_dlg=tk.Toplevel(self.parent,width=1000, height=100)
        self.unsucc=tk.Label(self.unsucc_dlg, text="Authentication unsuccessful")
        self.ok=tk.Button(self.unsucc_dlg, text="OK", command=self.unsucc_dlg.destroy)
        self.unsucc.grid(column=0,row=0)
        self.ok.grid(column=0, row=1)

    #this function will kill the authentication window and will invoke the Mainapp class which will be the main application window
    def gotoMainapp(self):
        self.success_dlg.destroy()
        MainApp(root)


#MainApp will bring forth the main app window after the successful authentication has taken place     
class MainApp(LoginApp):
    def __init__(self,parent):
        tk.Frame.__init__(self, parent)
        #the following command brings back the root window since we are now authenticated
        root.deiconify()
        self.parent = parent
        self.app = tk.Frame(self.parent, width=1000, height=100)
        self.instruction = tk.Label(self.app, text="Please issue your AXL query and hit EXECUTE")
        self.query = tk.Entry(self.app)
        self.execute = tk.Button(self.app, text="EXECUTE", command=self.executequery)
        self.cancel=tk.Button(self.app, text="CANCEL")

        # the following line use the grid geometry manager to put every widget to a designated place within the frame
        self.app.grid(column=0, row=0)
        self.instruction.grid(column=0,row=0,sticky=W)
        self.query.grid(column=0,row=1,columnspan=2, sticky=W+E)
        self.execute.grid(column=0,row=3, sticky=W+E)
        self.cancel.grid(column=1,row=3)

    # here I process the response of the query so that it is ready to be imported to a csv file using the csv module
    # I create nested lists; a list which contains sub-lists which in turn contain one full row
    def processquery(self):
        contents=list(map(list, self.result[0][0]))
        columns=[contents[0][x][0] for x in range(len(contents[0]))]
        self.columns_nested=[columns[i:i+len(columns)] for i in range(0,len(columns),len(columns))]
        data=[contents[y][z][1] for y in range(len(contents)) for z in range(len(contents[0]))]
        self.datalists=[data[i:i+len(contents[0])] for i in range(0,len(data),len(contents[0]))]
        self.write_to_csv(self.result[0][0])
            
    # in order to get the variables from the LoginApp class I had to make those variables class variables (prepend LoginApp) instead of
    # instance variables (prepend self)     
    def executequery(self):
        logging.getLogger('suds.client').setLevel(logging.DEBUG)
        logging.getLogger('suds.transport').setLevel(logging.DEBUG)
        logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
        url='file:///Users/chge/Documents/VNG/AXLToolkit/9.1/schema/current/AXLAPI.wsdl'
        client=Client(url,location=self.location,username=self.textuser.get(),password=self.textpass.get())
        self.result = client.service.executeSQLQuery(self.query.get())
        print(self.result)
        self.processquery()

    

    def write_to_csv(self, rows, filename='query_out.csv'):
        with open(filename, 'w') as fd:
            writer = csv.writer(fd,delimiter=',')
            writer.writerows(self.columns_nested)
            writer.writerows(self.datalists)
            fd.close()

root = tk.Tk()
root.title("Test SOAP Queries")
root1=tk.Toplevel()
login=LoginApp(root1)
root.mainloop

 

 

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...