2015-01-01 9 views
17

मैं एक उपयोगकर्ता सिस्टम बनाने की कोशिश कर रहा हूं, जो एक सेटिंग और गुई मॉड्यूल का उपयोग करता है, और जब गुई मॉड्यूल फ़ाइल के लिए अचार का उपयोग करके लोड करने के लिए अनुरोध करता है, तो मुझे एक विशेषता मिलती रहती है त्रुटि। इस सेटिंग मॉड्यूल से है:अचार और मल्टीपाइल मॉड्यूल का उपयोग कर फ़ाइलों को लोड करने में असमर्थ

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) 

और इस जीयूआई मॉड्यूल है:

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

प्रत्येक उपयोगकर्ता एक वर्ग है और एक सूची में डाल दिया जाता है और फिर सूची अचार का उपयोग कर सहेजा जाता है, जब मैं बस सेटिंग्स फ़ाइल को लोड और सत्यापित करें लॉगिन सब कुछ ठीक काम करता है, लेकिन जब मैं जीयूआई मॉड्यूल को खोलने और सत्यापित करें कोशिश यह मुझे नहीं करता है, त्रुटि मैं हो रही है:

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

मैं अगर यह आपकी समस्या से संबंधित है पता नहीं है, लेकिन आप की जरूरत नहीं है 'close' एक फाइल अगर आपने इसे 'with' का उपयोग करके खोला है। जब ब्लॉक समाप्त होता है तो संदर्भ प्रबंधक स्वचालित रूप से आपके लिए बंद कर देगा। साथ ही, आपकी 'सत्यापन उपयोगकर्ता' विधि ठीक से काम नहीं करती है। यह केवल उपयोगकर्ता सूची में पहले उपयोगकर्ता को देखता है। – Kevin

+0

फीडबैक के लिए धन्यवाद !, और हाँ मैंने केवल एक उपयोगकर्ता के साथ कोशिश की, मैं फिर से कर दूंगा कि क्या आपको पता है कि मुझे यह त्रुटि क्यों मिल रही है? – Inthuson

+0

क्या आप user_data.pkl फ़ाइल की सामग्री पोस्ट कर सकते हैं, यह मानते हुए कि यह इस चरण में परीक्षण डेटा है? – zehnpaard

उत्तर

26

मुद्दा यह है कि आप है ' पुनः वास्तव में 'सेटिंग' मॉड्यूल चलाकर सेटिंग्स में परिभाषित पिकलिंग ऑब्जेक्ट्स, तो आप GUI मॉड्यूल से ऑब्जेक्ट्स को अनपिक करने का प्रयास कर रहे हैं।

याद रखें कि अचार वास्तव में कक्षा/वस्तु का निर्माण कैसे किया जाता है, इस बारे में जानकारी संग्रहीत नहीं करता है, और जब अनपिकलिंग के दौरान कक्षा तक पहुंच की आवश्यकता होती है। अधिक जानकारी के लिए wiki on using Pickle देखें।

pkl डेटा में, आप देखते हैं कि वस्तु संदर्भित किया जा रहा __main__.Manager है, के रूप में 'सेटिंग' मॉड्यूल मुख्य था जब तुम अचार फ़ाइल बनाई (यानी के रूप में मुख्य स्क्रिप्ट आह्वान करने के लिए आप 'सेटिंग' मॉड्यूल भाग गया addUser फ़ंक्शन)।

फिर, आप 'गुई' में अनपिकलिंग करने का प्रयास करें - ताकि मॉड्यूल का नाम __main__ हो, और आप उस मॉड्यूल के भीतर सेटिंग आयात कर रहे हैं। तो निश्चित रूप से प्रबंधक वर्ग वास्तव में Settings.Manager होगा। लेकिन पीकेएल फ़ाइल यह नहीं जानता है, और प्रबंधक वर्ग को __main__ के भीतर देखता है, और एक विशेषता एरर फेंकता है क्योंकि यह अस्तित्व में नहीं है (Settings.Manager करता है, लेकिन __main__.Manager नहीं करता है)।

यहां प्रदर्शित करने के लिए एक न्यूनतम कोड सेट है।

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

आप उपरोक्त अचार डेटा उत्पन्न करने के लिए चलाते हैं। main_module.py मॉड्यूल:

import pickle 

import class_def 

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

आप उपरोक्त चलाने अचार फ़ाइल खोलने के लिए प्रयास करने के लिए है, और इस लगभग एक ही त्रुटि है कि आप देख रहे थे फेंकता है। (थोड़ा अलग है, लेकिन मेरा अनुमान है कि यह है कि क्योंकि मैं अजगर 2.7 पर हूँ)

समाधान या तो है:

  1. आप वर्ग शीर्ष स्तर के मॉड्यूल का नाम स्थान के अंदर उपलब्ध बनाने (यानी जीयूआई या main_module) एक स्पष्ट आयात के माध्यम से, या
  2. आप उसी शीर्ष-स्तरीय मॉड्यूल से पिकल फ़ाइल बनाते हैं, जिसे आप इसे खोलेंगे (यानी GUI से Settings.addUser पर कॉल करें, या मुख्य_मॉड्यूल से)। इसका अर्थ यह है कि पीकेएल फ़ाइल वस्तुओं को Settings.Manager या class_def.Foo के रूप में सहेज लेगी, जो GUI `main_module` नेमस्पेस में पाई जा सकती हैं।

विकल्प 1 उदाहरण:

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) 

विकल्प 2 उदाहरण:

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

धन्यवाद !! इससे वास्तव में मदद मिली, कार्यक्रम अब काम कर रहा है, आप उपयोगकर्ता कक्षाओं को आयात करने के बारे में सही थे, जो विकल्प 2 की तुलना में अधिक कुशल तरीके से दिखते हैं! – Inthuson

+0

सुनकर खुशी हुई! मैं सहमत हूं, इस स्तर पर जीयूआई मॉड्यूल में स्पष्ट रूप से प्रत्येक वर्ग को आयात करना बहुत आसान है। दूसरी तरफ, एक बार जब आप अपने कोड के साथ समाप्त कर लेंगे, तो मुझे लगता है कि आप जीयूआई इंटरफेस का उपयोग कर उपयोगकर्ताओं को जोड़/हटाएंगे - इसलिए आपकी ऑब्जेक्ट्स को जीआईआई के साथ __main__ मॉड्यूल के रूप में चुना जाएगा, और कक्षाएं सेटिंग्स होगी। उपयोगकर्ता, सेटिंग्स। प्रबंधक आदि – zehnpaard

+0

हाँ, क्योंकि यह सिर्फ लॉगिन gui है, मुझे लगता है कि अभी इसका कुशल है, अगर मेरे पास कोई और सवाल है तो बीटीडब्ल्यू? क्या मुझे फिर से पूछना चाहिए? – Inthuson

संबंधित मुद्दे