2015-01-01 16 views
17

Sto provando a creare un sistema utente, che utilizza un'impostazione e un modulo Gui, e quando il modulo GUI richiede il caricamento del file utilizzando pickle, continuo a ricevere un attributo errore. questo è dal modulo impostazioni:Impossibile caricare i file utilizzando i moduli pickle e multipile

import pickle 
import hashlib 

class User(object): 
     def __init__(self, fname, lname, dob, gender): 
       self.firstname = fname 
       self.lastname = lname 
       self._dob = dob 
       self.gender = gender 
       self.type = 'General' 
       self._username = '' 
       self._hashkey = '' 

     def Report(self): 
       print("Full Name: {0} {1}\nDate of Birth: {2}\nGender: {3}\nAccess Level: {4}".format(self.firstname,self.lastname, self._dob, self.gender, self.type)) 
       print(self._username) 

     def Genusername(self): 
       self._username = str(str(self._dob)[:2] + self.firstname[:2] + self.lastname[:2]) 
       saveUsers(users) 

     def Genhashkey(self, password): 
       encoded = password.encode('utf-8','strict') 
       return hashlib.sha256(encoded).hexdigest() 

     def Verifypassword(self, password): 
       if self._hashkey == self.Genhashkey(password): 
         return True 
       else: 
         return False 

class SAdmin(User): 
     def __init__(self, fname, lname, dob, gender): 
       super().__init__(fname, lname, dob, gender) 
       self.type = 'Stock Admin' 

class Manager(User): 
     def __init__(self, fname, lname, dob, gender): 
       super().__init__(fname, lname, dob, gender) 
       self.type = 'Manager' 

def saveUsers(users): 
     with open('user_data.pkl', 'wb') as file: 
      pickle.dump(users, file, -1) # PICKLE HIGHEST LEVEL PROTOCOL 

def loadUsers(users): 
     try:   
       with open('user_data.pkl', 'rb') as file: 
         temp = pickle.load(file) 
         for item in temp: 
           users.append(item) 
     except IOError: 
       saveUsers([]) 

def userReport(users): 
     for user in users: 
       print(user.firstname, user.lastname) 

def addUser(users): 
     fname = input('What is your First Name?\n > ') 
     lname = input('What is your Last Name?\n > ') 
     dob = int(input('Please enter your date of birth in the following format, example 12211996\n> ')) 
     gender = input("What is your gender? 'M' or 'F'\n >") 
     level = input("Enter the access level given to this user 'G', 'A', 'M'\n > ") 
     password = input("Enter a password:\n > ") 
     if level == 'G': 
       usertype = User 
     if level == 'A': 
       usertype = SAdmin 
     if level == 'M': 
       usertype = Manager 
     users.append(usertype(fname, lname, dob, gender)) 
     user = users[len(users)-1] 
     user.Genusername() 
     user._hashkey = user.Genhashkey(password) 
     saveUsers(users) 

def deleteUser(users): 
     userReport(users) 
     delete = input('Please type in the First Name of the user do you wish to delete:\n > ') 
     for user in users: 
       if user.firstname == delete: 
         users.remove(user) 
     saveUsers(users) 

def changePass(users): 
     userReport(users) 
     change = input('Please type in the First Name of the user you wish to change the password for :\n > ') 
     for user in users: 
       if user.firstname == change: 
         oldpass = input('Please type in your old password:\n > ') 
         newpass = input('Please type in your new password:\n > ') 
         if user.Verifypassword(oldpass): 
           user._hashkey = user.Genhashkey(newpass) 
           saveUsers(users) 
         else: 
           print('Your old password does not match!') 

def verifyUser(username, password): 
     for user in users: 
       if user._username == username and user.Verifypassword(password): 
         return True 
       else: 
         return False 


if __name__ == '__main__': 
     users = [] 
     loadUsers(users) 

e questo è il modulo GUI:

from PyQt4 import QtGui, QtCore 
import Settings 

class loginWindow(QtGui.QDialog):  
    def __init__(self): 
     super().__init__()   
     self.initUI() 

    def initUI(self): 
     self.lbl1 = QtGui.QLabel('Username') 
     self.lbl2 = QtGui.QLabel('Password') 
     self.username = QtGui.QLineEdit() 
     self.password = QtGui.QLineEdit() 

     self.okButton = QtGui.QPushButton("OK") 
     self.okButton.clicked.connect(self.tryLogin) 
     self.cancelButton = QtGui.QPushButton("Cancel") 

     grid = QtGui.QGridLayout() 
     grid.setSpacing(10) 

     grid.addWidget(self.lbl1, 1, 0) 
     grid.addWidget(self.username, 1, 1) 
     grid.addWidget(self.lbl2, 2, 0) 
     grid.addWidget(self.password, 2, 1) 
     grid.addWidget(self.okButton, 3, 1) 
     grid.addWidget(self.cancelButton, 3, 0) 

     self.setLayout(grid) 

     self.setGeometry(300, 300, 2950, 150) 
     self.setWindowTitle('Login') 
     self.show() 

    def tryLogin(self): 
     print(self.username.text(), self.password.text()) 
     if Settings.verifyUser(self.username.text(),self.password.text()): 
      print('it Woks') 
     else: 
      QtGui.QMessageBox.warning(
       self, 'Error', 'Incorrect Username or Password') 

class Window(QtGui.QMainWindow): 
    def __init__(self): 
     super().__init__()   


if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    users = [] 
    Settings.loadUsers(users) 
    if loginWindow().exec_() == QtGui.QDialog.Accepted: 
     window = Window() 
     window.show() 
     sys.exit(app.exec_()) 

ogni utente è una classe e sono messi in una lista e poi la lista viene salvato utilizzando sottaceto, quando ho caricare solo il file delle impostazioni e verificare il tutto login funziona bene, ma quando ho aperto il modulo GUI e cerco di verificare che non me lo permette, errore che sto ricevendo:

Traceback (most recent call last): 
    File "C:\Users`Program\LoginGUI.py", line 53, in <module> 
    Settings.loadUsers(users) 
    File "C:\Users\Program\Settings.py", line 51, in loadUsers 
    temp = pickle.load(file) 
AttributeError: Can't get attribute 'Manager' on <module '__main__' (built-in)> 
+1

Non so se questo è legato al tuo problema, ma non c'è bisogno di 'close' un file se lo hai aperto usando 'with'. Il gestore del contesto lo chiuderà automaticamente al termine del blocco con. Inoltre, il tuo metodo 'verifyUser' non funziona correttamente. Guarda sempre solo il primo utente nella lista utenti. – Kevin

+0

Grazie per il feedback! E sì, l'ho provato solo con un utente, lo rifarò perché sai che sto ottenendo quell'errore? – Inthuson

+0

Puoi postare il contenuto del file user_data.pkl, assumendo che si tratti di dati di test in questa fase? – zehnpaard

risposta

26

il problema è che si' re oggetti di decapaggio definiti in Impostazioni eseguendo effettivamente il modulo "Impostazioni", quindi si sta tentando di annullare l'inclusione degli oggetti dal modulo GUI.

Ricordare che pickle non archivia effettivamente le informazioni su come viene costruita una classe/oggetto e ha bisogno di accedere alla classe quando si deseleziona. Vedi wiki on using Pickle per maggiori dettagli.

Nei dati PKL, si vede che l'oggetto si fa riferimento è __main__.Manager, come modulo 'Impostazioni' stato principale momento della creazione del file di salamoia (cioè è stato eseguito il modulo 'Impostazioni', come lo script principale per invocare la funzione addUser).

Quindi, si prova a deselezionare in "Gui", in modo che il modulo abbia il nome __main__ e si sta importando l'impostazione in quel modulo. Quindi, ovviamente, la classe Manager sarà Settings.Manager. Ma il file pkl non lo sa, e cerca la classe Manager entro __main__ e lancia un AttributeError perché non esiste (Settings.Manager sì, ma non lo è __main__.Manager).

Ecco un codice minimo impostato per dimostrare.

Il modulo class_def.py:

import pickle 

class Foo(object): 
    def __init__(self, name): 
     self.name = name 

def main(): 
    foo = Foo('a') 
    with open('test_data.pkl', 'wb') as f: 
     pickle.dump([foo], f, -1) 

if __name__=='__main__': 
    main() 

Si esegue quanto sopra per generare i dati sottaceto. Il modulo main_module.py:

import pickle 

import class_def 

if __name__=='__main__': 
    with open('test_data.pkl', 'rb') as f: 
     users = pickle.load(f) 

si esegue il precedente per tentare di aprire il file salamoia, e questo getta più o meno lo stesso errore che si stavano vedendo. (Un po 'diversa, ma credo che sia perché sono in Python 2.7)

La soluzione può essere:

  1. a fare la classe a disposizione all'interno del namespace del modulo di livello superiore (es GUI o main_module) tramite un'importazione esplicita, oppure
  2. Si crea il file pickle dallo stesso modulo di livello superiore di quello in cui lo si apre (ovvero chiama Settings.addUser dalla GUI o class_def.main da main_module). Ciò significa che il file pkl salverà gli oggetti come Settings.Manager o class_def.Foo, che possono quindi essere trovati nello spazio dei nomi `main_module` GUI.

Opzione 1 Esempio:

import pickle 

import class_def 
from class_def import Foo # Import Foo into main_module's namespace explicitly 

if __name__=='__main__': 
    with open('test_data.pkl', 'rb') as f: 
     users = pickle.load(f) 

Opzione 2 Esempio:

import pickle 

import class_def 

if __name__=='__main__': 
    class_def.main() # Objects are being pickled with main_module as the top-level 
    with open('test_data.pkl', 'rb') as f: 
     users = pickle.load(f) 
+0

Grazie !! Questo mi ha davvero aiutato, il programma sta funzionando ora, avevi ragione a importare le classi utente, che sembra un modo più efficiente rispetto all'opzione 2! – Inthuson

+0

Felice di sentirlo! Sono d'accordo, in questa fase è molto più semplice importare ogni classe esplicitamente nel modulo della GUI. D'altra parte, una volta che hai finito con il tuo codice, immagino che aggiungerai/eliminerai utenti usando l'interfaccia della GUI - così i tuoi oggetti saranno decapitati con GUI come modulo __main__, e le classi saranno Settings.User, Impostazioni.Manager ecc. – zehnpaard

+0

Sì, dal momento che questo è solo il gui di accesso, immagino sia efficiente in questo momento, se avessi un'altra domanda? Dovrei chiedere di nuovo? – Inthuson

Problemi correlati