2015-01-01 12 views
17

Tôi đang cố tạo hệ thống người dùng, sử dụng mô-đun và mô-đun Gui và khi mô-đun gui yêu cầu tệp tải lên bằng cách sử dụng dưa, tôi tiếp tục nhận được thuộc tính lỗi. đây là từ các cài đặt mô-đun:Không thể tải các tệp bằng mô-đun chọn và mô-đun

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) 

và đây là mô-đun 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_()) 

mỗi người dùng là một lớp học và được đưa vào một danh sách và sau đó danh sách được lưu sử dụng dưa, khi tôi chỉ tải lên tệp cài đặt và xác minh đăng nhập mọi thứ hoạt động tốt nhưng khi tôi mở mô-đun gui và thử xác minh nó không cho tôi, lỗi tôi nhận được:

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

Tôi không biết nếu điều này có liên quan đến vấn đề của bạn, nhưng bạn không cần phải cho 'close' một tập tin nếu bạn mở nó bằng cách sử dụng 'with'. Trình quản lý ngữ cảnh sẽ tự động đóng nó cho bạn khi khối kết thúc. Ngoài ra, phương thức 'verifyUser' của bạn không hoạt động đúng cách. Nó chỉ bao giờ nhìn vào người dùng đầu tiên trong danh sách người dùng. – Kevin

+0

Cảm ơn bạn đã phản hồi !, vâng tôi chỉ thử nó với một người dùng, tôi sẽ làm lại mà bạn biết tại sao tôi nhận được lỗi đó? – Inthuson

+0

Bạn có thể đăng nội dung của tệp user_data.pkl, giả sử dữ liệu thử nghiệm của nó ở giai đoạn này không? – zehnpaard

Trả lời

26

Vấn đề là bạn ' re các đối tượng tẩy được xác định trong Cài đặt bằng cách thực sự chạy mô-đun 'Cài đặt', sau đó bạn đang cố gắng tháo các đối tượng khỏi mô-đun GUI.

Hãy nhớ rằng dưa chua không thực sự lưu trữ thông tin về cách lớp/đối tượng được xây dựng và cần quyền truy cập vào lớp khi bỏ ghim. Xem wiki on using Pickle để biết thêm chi tiết.

Trong dữ liệu PKL, bạn sẽ thấy rằng đối tượng đang được tham chiếu __main__.Manager, như mô-đun 'Cài đặt' là chính khi bạn đã tạo file dưa (ví dụ bạn chạy các mô-đun 'Cài đặt' như kịch bản chính để gọi chức năng addUser).

Sau đó, bạn thử bỏ chọn trong 'Gui' - để mô-đun đó có tên __main__ và bạn đang nhập Cài đặt trong mô-đun đó. Vì vậy, tất nhiên lớp Manager sẽ thực sự là Settings.Manager. Nhưng tệp pkl không biết điều này và tìm lớp Manager trong phạm vi __main__ và ném AttributeError vì nó không tồn tại (Settings.Manager, nhưng __main__.Manager thì không).

Đây là mã tối thiểu được đặt để minh họa.

Các class_def.py mô-đun:

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

Bạn chạy ở trên để tạo ra các dữ liệu dưa. Các main_module.py mô-đun:

import pickle 

import class_def 

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

Bạn chạy ở trên để cố gắng mở file dưa, và điều này ném xấp xỉ lỗi tương tự mà bạn đang nhìn thấy. (Hơi khác nhau, nhưng tôi đoán đó là bởi vì tôi đang trên Python 2.7)

Giải pháp là một trong hai:

  1. Bạn làm cho các lớp có sẵn trong không gian tên của các mô-đun cấp cao nhất (tức là GUI hoặc main_module) thông qua việc nhập rõ ràng hoặc
  2. Bạn tạo tệp dưa chuột từ cùng một mô-đun cấp cao nhất như mô-đun bạn sẽ mở trong đó (tức là gọi Settings.addUser từ GUI hoặc class_def.main từ main_module). Điều này có nghĩa là tệp pkl sẽ lưu các đối tượng dưới dạng Settings.Manager hoặc class_def.Foo, sau đó có thể được tìm thấy trong không gian tên GUI `main_module`.

Lựa chọn 1 ví dụ:

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) 

Lựa chọn 2 ví dụ:

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

Cảm ơn bạn !! Điều đó thực sự hữu ích, chương trình hiện đang hoạt động, bạn đã đúng về việc nhập các lớp người dùng, điều đó có vẻ như là một cách hiệu quả hơn so với tùy chọn 2! – Inthuson

+0

Rất vui khi biết điều đó! Tôi đồng ý, ở giai đoạn này, việc nhập khẩu từng lớp một cách rõ ràng trong mô-đun GUI trở nên đơn giản hơn rất nhiều. Mặt khác, khi bạn đã hoàn thành mã của mình, tôi tưởng tượng bạn sẽ thêm/xóa người dùng bằng giao diện GUI - vì vậy các đối tượng của bạn sẽ được chọn bằng GUI như mô-đun __main__ và các lớp sẽ là Settings.User, Settings.Manager vv – zehnpaard

+0

Vâng, vì đây chỉ là gui đăng nhập, tôi đoán hiệu quả của nó ngay bây giờ, btw nếu tôi có một câu hỏi khác? Tôi có nên hỏi lại không? – Inthuson

Các vấn đề liên quan