2015-01-01 12 views
17

Ich versuche ein Benutzersystem zu erstellen, das eine Einstellung und ein Gui-Modul verwendet. Wenn das GUI-Modul anfordert, dass die Datei mit Pickle geladen wird, erhalte ich ein Attribut Error. dies ist aus dem Einstellungsmodul:Dateien können nicht mit Pickle- und Multiple-Modulen geladen werden

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) 

und das ist die GUI-Modul:

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_()) 

jeder Benutzer ist eine Klasse und in eine Liste gesetzt und dann wird die Liste mit Gurke gespeichert, wenn i nur die Einstellungsdatei laden und überprüfen die Anmelde alles funktioniert gut, aber wenn ich die gUI-Modul öffnen und versuchen sicherzustellen, es läßt mich nicht, Fehler ich erhalte:

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

Ich weiß nicht, ob dies für Ihr Problem verwandt ist, aber Sie brauchen nicht zu 'close' eine Datei, wenn Sie sie mit 'mit' geöffnet haben. Der Context Manager schließt sie automatisch für Sie, wenn der with-Block endet. Außerdem funktioniert Ihre Methode 'verifyUser' nicht ordnungsgemäß. Es schaut immer nur auf den ersten Benutzer in der Benutzerliste. – Kevin

+0

Vielen Dank für die Rückmeldung!, Und ja, ich habe es nur mit einem Benutzer versucht, ich werde wiederholen, wissen Sie, warum ich diesen Fehler bekomme? – Inthuson

+0

Können Sie den Inhalt der Datei "user_data.pkl" posten, wenn Sie davon ausgehen, dass es zu diesem Zeitpunkt Testdaten gibt? – zehnpaard

Antwort

26

das Problem ist, dass Sie‘ zu Inaktivieren von Objekten, die unter Einstellungen definiert wurden, indem das Modul "Einstellungen" tatsächlich ausgeführt wird. Dann versuchen Sie, die Objekte aus dem Modul GUI zu entpacken.

Denken Sie daran, dass Gurke nicht tatsächlich Informationen über die Konstruktion einer Klasse/eines Objekts speichert und beim Entpacken auf die Klasse zugreifen muss. Weitere Details finden Sie unter wiki on using Pickle.

In der PKL-Daten finden Sie, dass das Objekt __main__.Manager verwiesen wird, wie das Modul ‚Einstellungen‘ Haupt war, wenn Sie die Beize-Datei erstellt (dh Sie ‚Einstellungen‘ Modul als das Hauptskript aufzurufen lief die addUser Funktion).

Dann versuchen Sie, in 'Gui' zu entpacken - so dass das Modul den Namen __main__ hat und Sie Einstellungen innerhalb dieses Moduls importieren. Natürlich wird die Manager-Klasse Settings.Manager sein. Aber die pkl-Datei weiß das nicht und sucht nach der Manager-Klasse innerhalb __main__ und löst einen AttributeError aus, weil er nicht existiert (Settings.Manager tut, aber __main__.Manager nicht).

Hier ist ein minimaler Code festgelegt, um zu demonstrieren.

Das class_def.py Modul:

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() 

Sie führen die oben die Beize Daten zu erzeugen. Das main_module.py Modul:

import pickle 

import class_def 

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

Sie die oben laufen zu versuchen, die Beize-Datei zu öffnen, und dies wirft etwa den gleichen Fehler, die Sie sahen. (Ein wenig anders, aber ich vermute, das ist, weil ich auf Python bin 2.7)

Die Lösung ist entweder:

  1. Sie machen die Klasse zur Verfügung im Namensraum des Top-Level-Modul (dh GUI oder main_module) durch einen expliziten Import, oder
  2. Sie erstellen die Beizdatei aus dem gleichen Modul der obersten Ebene wie dem, in dem Sie sie öffnen (dh rufen Sie Settings.addUser von GUI oder class_def.main von main_module). Das bedeutet, dass die pkl-Datei die Objekte als Settings.Manager oder class_def.Foo speichert, die dann im Namespace "main_module" GUI gefunden werden können.

Option 1 Beispiel:

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) 

Option 2 Beispiel:

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

Vielen Dank !! Das hat wirklich geholfen, das Programm funktioniert jetzt, Sie hatten recht, die Benutzerklassen zu importieren, das scheint ein effizienterer Weg zu sein als Option 2! – Inthuson

+0

Froh, das zu hören! Ich stimme zu, in diesem Stadium ist es viel einfacher, jede Klasse explizit im GUI-Modul zu importieren. Auf der anderen Seite, wenn Sie mit Ihrem Code fertig sind, stelle ich mir vor, dass Sie Benutzer über die GUI-Schnittstelle hinzufügen/löschen werden - also werden Ihre Objekte mit der GUI als __main__-Modul markiert, und die Klassen sind Settings.User, Settings.Manager etc. – zehnpaard

+0

Ja, da dies nur der Login gui ist, denke ich, es ist effizient jetzt, btw, wenn ich eine andere Frage habe? Soll ich nochmal fragen? – Inthuson

Verwandte Themen