Estoy tratando de crear un usuario del sistema, que utiliza una configuración y la interfaz de usuario del módulo, y cuando la interfaz gráfica de usuario del módulo de solicitudes para el archivo a cargar con el uso de la salmuera, sigo recibiendo un atributo de error. esto es desde el módulo de configuración:

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)

y esta es la interfaz gráfica de usuario del módulo:

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

de cada usuario es una clase y se ponen en una lista y, a continuación, la lista se guarda el uso de la salmuera cuando me carga solo el archivo de configuración y comprobar el inicio de sesión todo funciona bien pero cuando voy a abrir la interfaz gráfica de usuario del módulo y tratar de comprobar que no me deja, el error que estoy consiguiendo:

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)>
  • No sé si esto está relacionado con su problema, pero no es necesario close un archivo si se hubiera abierto el uso de with. El contexto del administrador, se cierra automáticamente cuando el bloque termina. También, su verifyUser método no funciona correctamente. Sólo se ve en el primer usuario en la lista.
  • Gracias por los comentarios!, y sí, yo sólo lo probé con un usuario, yo lo haria que ¿sabe usted por qué estoy recibiendo ese error?
  • Puedes publicar el contenido de la user_data.pkl archivo, asumiendo que se trata de datos de prueba en esta etapa?
  • €•Ñ ]”Œ__main__”ŒManager”“”)}”’”}”(Œlastname”ŒHammer”Œgender”ŒM”Œ_dob”JüxËŒ_hashkey”Œ@99b3bcf690e653a177c602dd9999093b9eb29e50a3af9a059af3fcbfab476a16”Œ _username”Œ30JaHa”Œtype”hŒ firstname”ŒJack”uba.Es un archivo pickle así que sí, sombreros de lo que parece, se trata de un objeto que contenga nombre,apellidos, fecha de NACIMIENTO, nombre de usuario, hashkey(contraseña), y acceslevel
  • a la derecha, tres más preguntas – son sus objetos de usuario creado a partir de una clase que se llama Administrador? Es esta definido en el módulo de Configuración? ¿Cómo crear realmente user_data.pkl?
  • hay una clase principal llamada de usuario, a continuación, subclases este es uno de los manager de la subclase y sí, las clases son todos creados en el módulo de configuración: def saveUsers(users): with open('user_data.pkl', 'wb') as file: pickle.dump(users, file, -1) y se cargan por esta función: 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([])
  • OK gracias, creo que el código no los detalles de su ventana de inicio de sesión, sino que las definiciones de clase para los usuarios individuales. Cómo de grande es su módulo de Configuración? Es lo suficientemente pequeño como para que usted pueda editar la pregunta y añadir el módulo completo en lugar de sólo las tres funciones y la name__==’__main‘ cláusula?
  • bueno añadido el modulo completo hay que ir, no es tan grande tbh

InformationsquelleAutor Inthuson | 2015-01-01

3 Comentarios

  1. 52

    El problema es que estás el decapado de los objetos definidos en la Configuración por que realmente ejecuta el ‘Ajustes’ del módulo de, entonces usted está tratando de unpickle los objetos de la GUI módulo.

    Recordar que pepinillos en realidad no almacenar información acerca de cómo una clase/objeto es construido, y las necesidades de acceso a la clase cuando unpickling. Ver wiki sobre el uso de la Salmuera para obtener más detalles.

    En el pkl de datos, se puede ver que el objeto al que se hace referencia es __main__.Manager, como el de ‘Ajustes’ el módulo principal cuando se creó el archivo pickle (es decir, se ejecutó el ‘Ajustes’ que el módulo principal de la secuencia de comandos para invocar la addUser función).

    A continuación, intenta unpickling en ‘Gui’ – por lo que el módulo tiene el nombre __main__, y va a importar Configuración dentro de ese módulo. Por supuesto, el Gerente de la clase será en realidad Settings.Manager. Pero el pkl archivo no sabe de esto, y se ve por el Gerente de la clase dentro de __main__, y lanza un AttributeError porque no existe ( Settings.Manager , pero __main__.Manager no).

    Aquí un mínimo conjunto de códigos a demostrar.

    La class_def.py módulo:

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

    Ejecutar el anterior para generar el pepinillo de datos.
    El main_module.py módulo:

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

    Ejecutar el anterior para intentar abrir el archivo pickle, y esto arroja aproximadamente el mismo error que estaban viendo. (Ligeramente diferentes, pero supongo que es porque estoy en Python 2.7)

    La solución es:

    1. De hacer la clase disponible en el espacio de nombres de la parte superior a nivel de módulo (es decir, la interfaz gráfica de usuario o main_module) a través de una explícita de importación, o
    2. De crear el archivo pickle de la misma superior a nivel de módulo como el que usted va a abrir en (es decir, de la llamada Settings.addUser de interfaz gráfica de usuario, o class_def.main de main_module). Esto significa que el pkl archivo guardar los objetos como Settings.Manager o class_def.Foo, que se pueden encontrar en la GUI`main_module` espacio de nombres.

    Opción 1 ejemplo:

    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)

    Opción 2 ejemplo:

    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)
    • Gracias!! Que realmente me ayudó, el programa está trabajando ahora, que estaban en lo correcto acerca de la importación de las clases de usuario, que parece una forma más eficiente que la opción 2!
    • Me alegro de oír eso! Estoy de acuerdo, en esta etapa, es mucho más fácil importar cada clase de forma explícita en la interfaz de usuario del módulo. Por otro lado, una vez que hayas terminado con tu código, me imagino que va a agregar/eliminar usuarios utilizando la interfaz gráfica de usuario, de forma que los objetos serán en escabeche con la interfaz gráfica como la principal módulo, y las clases serán los Ajustes.De Usuario, De Configuración.Manager, etc.
    • Sí, ya que esto es sólo el inicio de sesión gui supongo que su eficiente ahora, por cierto, si tengo otra pregunta? Debo volver a preguntar?
    • Sí, si es un tema aparte, entonces es mejor crear otra cuestión de seguir sumando a esta.
    • sería útil si usted sabe cómo hacer esto? parte de un mismo proyecto! stackoverflow.com/questions/27745094/…
    • He leído esta respuesta y yo que pensaba. «¡Por Supuesto!!!». Tome sus puntos de hombre bueno.

  2. 17

    Por favor, primero lea la respuesta mencionado por zehnpaard saber la razón para el atributo de error. Aparte de la solución que él ya prestados, en python3 puede utilizar el pickle.Unpickler clase y reemplazar el find_class método como se menciona a continuación:

    import pickle
    class CustomUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
    if name == 'Manager':
    from settings import Manager
    return Manager
    return super().find_class(module, name)
    pickle_data = CustomUnpickler(open('file_path.pkl', 'rb')).load()
    • Impresionante! Me parece que esta solución sea más robusto que zehnpaard aceptados por la respuesta, ya que permite cambiar la ubicación de la clase (o la función) código, en lugar de generado en la salmuera.
    • A nadie preguntando, esta solución se extiende a varias de las importaciones, sólo añadir más si las declaraciones.
    • sí, usted puede hacer eso también
  3. 0

    Si usted tiene una clase definida fuera del módulo, cuyo objeto es la de pickle de datos,
    usted tiene que importar la clase

    from outside_module import DefinedClass1, DefinedClass2, DefinedClass3 
    with open('pickle_file.pkl', 'rb') as f:
    pickle_data = pickle.load(f)

Dejar respuesta

Please enter your comment!
Please enter your name here