2

I am trying to write & display the id ,name and salary of 3 employees from .dat file using pickle methods in Python but while displaying I am able to see only 1 employee details the rest are not coming. Please suggest as where the problem is in the below code.

import pickle

class Emp:
    def __init__(self, id, name, sal):
        self.id = id
        self.name = name
        self.sal = sal
    def display(self):
        print('{} {} {}'.format(self.id, self.name, self.sal))
    
n = int(input('How many employees?'))
for i in range(n):
    id = int(input('Enter the id:'))
    name = input('Enter name:')
    sal = float(input('Enter salary: '))
    f = open('emp.dat', 'wb')    
    e = Emp(id, name, sal)
    pickle.dump(e, f)
f = open('emp.dat', 'rb')
print('Employee details: ')
obj = pickle.load(f)
obj.display()

Example run:

INPUT: 
How many employees?2
Enter the id:12
Enter name:john
Enter salary: 89000
Enter the id:34
Enter name:mark
Enter salary: 83111
obj.display()
OUTPUT:
Employee details: 
12 john 89000.0
4
  • 2
    Off-topic: look up the with statement. It avoids having to explicitly close the file every time. Commented May 11, 2021 at 11:39
  • @Maaz Is there any way to bring the cursor to the next line if i want to use 'wb', i want the cursor to move to the next line at each iteration Commented May 11, 2021 at 12:21
  • Open the file once, before the loop... You also never close the files Commented May 11, 2021 at 12:31
  • Just add an "\n" at the end, and you'll start on a new line. But please be careful with using wb, as @Tomerikoo rightfully suggested, it "truncates the file upon opening". Commented May 11, 2021 at 12:38

2 Answers 2

2

You're opening the file using wb (write binary). The w mode truncates (empties) the file upon opening, so you're effectively overwriting the records as you go.

Instead use ab (append binary) (and as @Maaz mentioned, use the with statement).

Furthermore, when reading data from the file, you will need to loop for as long as you can to read all of the records. (Happily pickle is a concatenation-tolerant format, so you can just read and read.)

import pickle


class Emp:
    def __init__(self, id, name, sal):
        self.id = id
        self.name = name
        self.sal = sal

    def display(self):
        print("{} {} {}".format(self.id, self.name, self.sal))


n = int(input("How many employees?"))
for i in range(n):
    id = int(input("Enter the id:"))
    name = input("Enter name:")
    sal = float(input("Enter salary: "))
    with open("emp.dat", "ab") as f:
        e = Emp(id, name, sal)
        pickle.dump(e, f)

with open("emp.dat", "rb") as f:
    while True:
        try:
            obj = pickle.load(f)
        except EOFError:  # Nothing to read
            break
        print("Employee details: ")
        obj.display()

Alternately (as discussed in comments), if you want to clear the file but write a number of new records, open the file in w mode only once, then write into it multiple times.

with open("emp.dat", "wb") as f:
    for i in range(n):
        id = int(input("Enter the id:"))
        name = input("Enter name:")
        sal = float(input("Enter salary: "))
        e = Emp(id, name, sal)
        pickle.dump(e, f)
Sign up to request clarification or add additional context in comments.

6 Comments

is there any way to bring the cursor to the next line while using 'wb'. I mean during each iteration the cursor should come to the next line while continue using open function
this is appending after previous i do not want to see any records at each fresh run of the program
There should be no such thing as "next line" when using binary files.
See my edit – to clear the file and write new records, open it once using the wb mode.
I have edited your read code in order to display the print statement only once rather than printing each time : with open("emp.dat", "rb") as f: print("Employee details: ") while True: try: obj = pickle.load(f) obj.display() except EOFError: # Nothing to read break
|
0
import pickle

class Emp:
    def __init__(self, id, name, sal):
        self.id = id
        self.name = name
        self.sal = sal
    def display(self):
        print('{} {} {}'.format(self.id, self.name, self.sal))

n = int(input('How many employees?'))
emps = []
for i in range(n):
    id = int(input('Enter the id:'))
    name = input('Enter name:')
    sal = float(input('Enter salary: '))
    e = Emp(id, name, sal)
    emps.append(e)
with open('emp.dat', 'wb') as f:
    pickle.dump(emps, f)
with open('emp.dat', 'rb') as f:
    print('Employee details: ')
    objs = pickle.load(f)
    for obj in objs:
        obj.display()

Example run:

How many employees?2
Enter the id:1
Enter name:a
Enter salary: 10
Enter the id:2
Enter name:b
Enter salary: 20
Employee details: 
1 a 10.0
2 b 20.0

2 Comments

This is not exactly the same thing – it's writing a single list object into the file, not several "free" objects.
Agree with you @AKX

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.