beastgr Δημοσ. 23 Σεπτεμβρίου 2014 Δημοσ. 23 Σεπτεμβρίου 2014 (επεξεργασμένο) Δεν είμαι καθόλου έμπειρος με προγραμματισμό και 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 πχ Αν θέλετε μπορώ να δώσω περισσότερες λεπτομέρειες Ευχαριστώ Επεξ/σία 23 Σεπτεμβρίου 2014 από beastgr
warchief Δημοσ. 24 Σεπτεμβρίου 2014 Δημοσ. 24 Σεπτεμβρίου 2014 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() Δεν θα επρεπε να σε μπερδευει νομιζω..
beastgr Δημοσ. 24 Σεπτεμβρίου 2014 Μέλος Δημοσ. 24 Σεπτεμβρίου 2014 Ευχαριστώ! Για κάποιον που άρχισε να ασχολείται με προγραμματισμό (και δη με 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 ώστε να τις γράψω σε ένα αρχείο. Μάλλον θα υπάρχει πιο ευκολος τρόπος απλά δεν έχω ακομα τις ικανότητες να τον βρω
beastgr Δημοσ. 24 Σεπτεμβρίου 2014 Μέλος Δημοσ. 24 Σεπτεμβρίου 2014 warchief o κώδικας που μου έδωσες βοήθησε. Τελικά τα κατάφερα χρησιμοποιώντας το csv module (που δεν το ήξερα είναι η αλήθεια) και με πολύ trial&error τα κατάφερα Όπως είπα ο κώδικας μου σίγουρα δε θα είναι ο βέλτιστος ίσα ίσα χάλια μάλλον είναι αλλά στο στάδιο που βρίσκομαι, είμαι χαρούμενος που απλά δουλεύει
warchief Δημοσ. 24 Σεπτεμβρίου 2014 Δημοσ. 24 Σεπτεμβρίου 2014 warchief o κώδικας που μου έδωσες βοήθησε. Τελικά τα κατάφερα χρησιμοποιώντας το csv module (που δεν το ήξερα είναι η αλήθεια) και με πολύ trial&error τα κατάφερα Όπως είπα ο κώδικας μου σίγουρα δε θα είναι ο βέλτιστος ίσα ίσα χάλια μάλλον είναι αλλά στο στάδιο που βρίσκομαι, είμαι χαρούμενος που απλά δουλεύει Assumptions is the mother of all evil.. Οπως εδωσες το φορμαρισμενο print του result και επειδή ειχε αγκυλες {} με key, value pairs υπεθεσα πως το καθε row το κανει wrap σαν python dictionary.. Κανε paste του κωδικα που εχεις να δουμε αν μπορει να γινει καλυτερα.
beastgr Δημοσ. 25 Σεπτεμβρίου 2014 Μέλος Δημοσ. 25 Σεπτεμβρίου 2014 Εγώ να δεις πόσο χρόνο μου πήρε να βρω πως θα έχω πρόσβαση στα 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
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα