2

When I run the code below I get this error message "EOFError: Ran out of input" what does it mean?? How it can be corrected?? and how to output the records details on the screen.

import pickle # this library is required to create binary files
class CarRecord:
    def __init__(self):
      self.VehicleID = " "          
      self.Registration = " "
      self.DateOfRegistration = " "
      self.EngineSize = 0           
      self.PurchasePrice = 0.00

ThisCar = CarRecord()
Car = [ThisCar for i in range(2)] # list of 2 car records

Car[0].VehicleID = "CD333"
Car[0].Registration = "17888"
Car[0].DateOfRegistration = "18/2/2017"
Car[0].EngineSize = 2500
Car[0].PurchasePrice = 22000.00

Car[1].VehicleID = "AB123"
Car[1].Registration = "16988"
Car[1].DateOfRegistration = "19/2/2017"
Car[1].EngineSize = 2500
Car[1].PurchasePrice = 20000.00

CarFile = open ('Cars.TXT', 'wb' ) # open file for binary write
for j in range (2): # loop for each array element
    pickle.dump (Car[j], CarFile) # write a whole record to the binary file
CarFile.close() # close file

CarFile = open ('Cars.TXT','rb') # open file for binary read
Car = [] # start with empty list
while True: #check for end of file
    Car.append(pickle.load(CarFile)) # append record from file to end of list
CarFile.close()
wovano
  • 4,543
  • 5
  • 22
  • 49
Chris
  • 21
  • 1
  • 1
  • 4

3 Answers3

6

Short answer: The simplest solution is to write the complete list to file using pickle.dump(). There's no need to write all objects one by one in a loop. Pickle is designed to do this for you.

Example code and alternative solutions:

Below is a fully working example. Some notes:

  • I've updated your __init__ function a bit to make the initialization code a lot easier and shorter.
  • I've also added a __repr__ function. This could be used to print the record details to screen, which you also asked. (Note that you could also implement a __str__ function, but I chose to implement __repr__ for this example).
  • This code example uses standard Python coding styles (PEP-8).
  • This code uses a context manager to open the file. This is safer and avoid the need to manually close the file.

If you really want to write the objects manually, for whatever reason, there are a few alternatives to do that safely. I'll explain them after this code example:

import pickle


class CarRecord:

    def __init__(self, vehicle_id, registration, registration_date, engine_size, purchase_price):
        self.vehicle_id = vehicle_id
        self.registration = registration
        self.registration_date = registration_date
        self.engine_size = engine_size
        self.purchase_price = purchase_price

    def __repr__(self):
        return "CarRecord(%r, %r, %r, %r, %r)" % (self.vehicle_id, self.registration,
                                                  self.registration_date, self.engine_size,
                                                  self.purchase_price)


def main():
    cars = [
        CarRecord("CD333", "17888", "18/2/2017", 2500, 22000.00),
        CarRecord("AB123", "16988", "19/2/2017", 2500, 20000.00),
    ]

    # Write cars to file.
    with open('Cars.TXT', 'wb') as car_file:
        pickle.dump(cars, car_file)

    # Read cars from file.
    with open('Cars.TXT', 'rb') as car_file:
        cars = pickle.load(car_file)

    # Print cars.
    for car in cars:
        print(car)


if __name__ == '__main__':
    main()

Output:

CarRecord('CD333', '17888', '18/2/2017', 2500, 22000.0)
CarRecord('AB123', '16988', '19/2/2017', 2500, 20000.0)

Instead of dumping the list at once, you could also do it in a loop. The following code snippets are alternative implementations to "Write cars to file" and "Read cars from file".

Alternative 1: write number of objects to file

At the start of the file, write the number of cars. This can be used to read the same amount of cars from the file.

    # Write cars to file.
    with open('Cars.TXT', 'wb') as car_file:
        pickle.dump(len(cars), car_file)
        for car in cars:
            pickle.dump(car, car_file)

    # Read cars from file.
    with open('Cars.TXT', 'rb') as car_file:
        num_cars = pickle.load(car_file)
        cars = [pickle.load(car_file) for _ in range(num_cars)]

Alternative 2: use an "end" marker

At the end of the file, write some recognizable value, for example None. When reading this object can be used to detect the end of file.

    # Write cars to file.
    with open('Cars.TXT', 'wb') as car_file:
        for car in cars:
            pickle.dump(car, car_file)
        pickle.dump(None, car_file)

    # Read cars from file.
    with open('Cars.TXT', 'rb') as car_file:
        cars = []
        while True:
            car = pickle.load(car_file)
            if car is None:
                break
            cars.append(car)
wovano
  • 4,543
  • 5
  • 22
  • 49
1

You can change you while loop to this:

this will break out of your while loop at the end of the input when it recieves the EOFError

while True: #check for end of file
    try:
        Car.append(pickle.load(CarFile)) # append record from file to end of list
    except EOFError:
        break
CarFile.close()
WhatsThePoint
  • 3,395
  • 8
  • 31
  • 53
0

You get that error when the file you are trying to load with pickle is empty.So make sure that there's things written into '.pkl file'