Python Forum
Using multiprocessing to produce objects for i in range
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using multiprocessing to produce objects for i in range
#7
(Feb-02-2022, 01:35 PM)deanhystad Wrote: The difference between windows and unix is windows spawns a fresh process with all new global variables. This means each process has it's own global hotel[] and nobody adds items to the hotel[] in the parent process. To get around this you do not use global variables, but instead use local variables which are passed as arguments to the child processes.

In unix a process is forked. It starts out as an exact copy of the parent. This means the child processes have the same global variables as the parent processes.

Ok, so I have to be honest. I don't understand python well enough to work with the manager yet, so I tried to use Queue, which actually worked!
Thing is. It only works as long as the number of objects doesn't exceed 584.
Any idea what the reason for this could be? It just stops doing anything when I enter something higher than 584, which is an oddly specific number.

EDIT: Actually, I can reach even higher numbers, but it doesn't always succeed. The runs seem to be more likely to succeed when they are a multiple of 4.


import random
import multiprocessing as mp

guestsUnderage = 0
guestsUnderageMale = 0
guestsUnderageFemale = 0
guestsAdults = 0
guestsTotal = 0

guestsEurope = 0
guestsAsia = 0
guestsAmericas = 0
guestsAfrica = 0
guestsAustralia = 0
numberPredominantOrigins = 0

number_of_guests = 0
guestsPerThread = 0
guestsFraction = 0

hotel = []
hotel1 = []

origins = ['Europe', 'Africa', 'The Americas', 'Asia', 'Australia'] #List of possible origins. I have not yet used this attribute for anything in the statistics.
ages = range(10,70) #List of possible ages. This is a list of integers!!! Hence, it might need to be changed into a string depending on the situation it is to be used in. (see line 25)
genders = ['male', 'female']


class Tenant: #Definies what attributes the tenant (i.e. object) will have
    roomNumberCount = 1

    __slots__ = ['roomNumber', 'origin', 'age', 'gender']
    def __init__(self, roomNumber, origin, age, gender):
        self.roomNumber = roomNumber
        self.origin = origin #String with origin name
        self.age = age #This will be a string! Hence it might need to be changed into an integer depending on the situation. (see line 31)
        self.gender = gender
        Tenant.roomNumberCount += 1
 
    def __str__(self): #Structure of the output when calling upon a tenant (i.e. object)
        return f'\nRoom Number: {str(self.roomNumber)} \nOrigin: {self.origin} \nAge: {str(self.age)} \nGender: {self.gender}'
 

def produceTenants1(q,x):
    hotel = []
    for i in range(x): #Random number of rooms between 20 and 40
        tenanti = Tenant(str(Tenant.roomNumberCount),origins[random.randint(0, len(origins) - 1)], str(ages[random.randint(0, len(ages) - 1)]), genders[random.randint(0, len(genders)-1)]) #Tells python the object class (i.e. Tenant) and where to get the attribute information from. In this case each attribute's value was chosen at random from the selection above. The first list point in the list is 0!!!, so we have to subtract 1 from the total length of each list, otherwise it might chose an option outside the range which would give us an error.
        hotel.append(tenanti) #Puts the tenants into the hotel
    q.put(hotel)

        

def produceTenants2():
    for i in range(guestsFraction): #Random number of rooms between 20 and 40
        tenanti = Tenant(str(Tenant.roomNumberCount),origins[random.randint(0, len(origins) - 1)], str(ages[random.randint(0, len(ages) - 1)]), genders[random.randint(0, len(genders)-1)]) #Tells python the object class (i.e. Tenant) and where to get the attribute information from. In this case each attribute's value was chosen at random from the selection above. The first list point in the list is 0!!!, so we have to subtract 1 from the total length of each list, otherwise it might chose an option outside the range which would give us an error.
        hotel1.append(tenanti) #Puts the tenants into the hotel

def main():
    global number_of_guests, guestsPerThread, guestsFraction

    try: # Number of guests determined by user input
        number_of_guests = int(input("How many people have checked in?"))
    except Exception as exception:  # If number is not integer 
        number_of_guests = 100
        if (type(exception).__name__) == 'ValueError':
            print('Entered value has to be integer! Setting number to default value (>>100<< guests).')
        else:
            print(f'{type(exception).__name__}! Setting number to default value (>>100<< guests).')
    
    guestsPerThread = number_of_guests // 4
    guestsFraction = number_of_guests % 4

    q = mp.Queue()
    p1 = mp.Process(target = produceTenants1, args = (q,guestsPerThread))
    p2 = mp.Process(target = produceTenants1, args = (q,guestsPerThread))
    p3 = mp.Process(target = produceTenants1, args = (q,guestsPerThread))
    p4 = mp.Process(target = produceTenants1, args = (q,guestsPerThread))
    
    p1.start()
    p2.start()
    p3.start()
    p4.start()

    p1.join()
    hotel = q.get()
    p2.join()
    hotel = hotel + q.get()
    p3.join()
    hotel = hotel + q.get()
    p4.join()
    hotel = hotel + q.get()



    produceTenants2()

    hotel = hotel + hotel1
    global guestsTotal, guestsUnderage, guestsUnderageFemale, guestsUnderageMale, guestsAdults, guestsEurope, guestsAfrica, guestsAsia, guestsAmericas, guestsAustralia, numberPredominantOrigins
    
    for guest in hotel: #guest is used to differentiate from Tenant and tenanti. Could have been used interchangably, though.
        guestsTotal += 1
        origin = guest.origin
        if int(guest.age) < 18:
            guestsUnderage += 1
    
            if guest.gender == 'male':
                guestsUnderageMale += 1
            else:
                guestsUnderageFemale += 1
        else:
            guestsAdults += 1

        match origin:
            case 'Europe':
                guestsEurope += 1
            case 'Africa':
                guestsAfrica += 1
            case 'Asia':
                guestsAsia += 1
            case 'The Americas':
                guestsAmericas += 1
            case 'Australia':
                guestsAustralia += 1


    for guest in hotel:
        if int(guest.roomNumber) <= 5: # This is just to verify that the room numbers are successive
            print(guest)
        else:
            break

    originDictionary = {'Europe': guestsEurope, 'Africa': guestsAfrica, 'Asia': guestsAsia, 'The Americas': guestsAmericas, 'Australia': guestsAustralia}


    guestsFromPredominantOrigin = originDictionary.get(max(originDictionary, key=originDictionary.get)) # String associated with the largest value in the dictionary. Still haven't figured out what to do if there are two equal values at the top.
    predominantOrigin = []
    for k, v in originDictionary.items():
        if v == guestsFromPredominantOrigin:
            predominantOrigin.append(k)
            numberPredominantOrigins += 1 # I will change the list below so I need this separate counter at the end

    delimiter = ' or '
    if len(predominantOrigin) == 1:
        predominantOrigin = delimiter.join(predominantOrigin)
    else:
        predominantOrigin = delimiter.join([", ".join(predominantOrigin[:-1]),predominantOrigin[-1]])


    print(f'{guestsTotal} guests have checked into the hotel. {guestsUnderage} were underage and among those, {guestsUnderageFemale} were female and {guestsUnderageMale} were male. Most people came from {predominantOrigin}, numbering {guestsFromPredominantOrigin}' + ('.' if numberPredominantOrigins == 1 else ' each.'))

if __name__ == "__main__":

    main()
Reply


Messages In This Thread
RE: Using multiprocessing to produce objects for i in range - by lucasrohr - Feb-02-2022, 03:53 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Produce One file Per PurchaseOrder jland47 1 372 Jan-26-2024, 11:38 AM
Last Post: Larz60+
  matplotlib x axis range goes over the set range Pedroski55 5 3,291 Nov-21-2021, 08:40 AM
Last Post: paul18fr
Photo multiprocessing with objects? - help m3atwad 0 1,289 Nov-17-2020, 03:16 AM
Last Post: m3atwad
  Define a range, return all numbers of range that are NOT in csv data KiNeMs 18 7,178 Jan-24-2020, 06:19 AM
Last Post: KiNeMs
  Can the comments produce errors in python? newbieAuggie2019 9 4,399 Nov-26-2019, 12:19 AM
Last Post: micseydel
  Code works in IDLE, appears to work in CMD, but won't produce files in CMD/Windows ChrisPy33 3 3,275 Jun-12-2019, 05:56 AM
Last Post: ChrisPy33
  \t produce eight gap but tab only produce four gap liuzhiheng 3 2,408 Jun-09-2019, 07:05 PM
Last Post: Gribouillis
  Python Script to Produce Difference Between Files and Resolve DNS Query for the Outpu sultan 2 2,560 May-22-2019, 07:20 AM
Last Post: buran
  Convert file sizes: will this produce accurate results? RickyWilson 2 8,194 Dec-04-2017, 03:36 PM
Last Post: snippsat
  How can I produce a list of n times the same element? JoeB 6 3,812 Nov-27-2017, 10:40 PM
Last Post: wavic

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020