In the python multiprocessing library, do processes spawned via Pool only have access to global variables bound at the time of Pool construction?
Why is this?
This appears to be the case, based on this experiment.
This code:
from multiprocessing import Pool
x = 0
class MyClass:
def get_x(self, i):
global x
return x
def foo():
global x
p = Pool(5)
for i in range(3):
x = i
c = MyClass()
print(list(p.imap(c.get_x, range(10*i, 10*i+10))))
foo()
produces the output
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Whereas moving the Pool construction inside the loop, i.e.
from multiprocessing import Pool
x = 0
class MyClass:
def get_x(self, i):
global x
return x
def foo():
global x
for i in range(3):
p = Pool(5)
x = i
c = MyClass()
print(list(p.imap(c.get_x, range(10*i, 10*i+10))))
foo()
produces the output
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
(Note that my motivation for wanting to do this is that x is a large pandas DataFrame in my real application, that needs to be read, but not modified, by several processes.)
My two questions are:
Is it merely impossible to rebind x once the processes are created?
Or do the processes each make a copy of x, and modification is impossible?
Related
I'm having issues with the code below where it's not displaying any paths for each vertex. Vertex and Distance from the source is displaying correctly, but for the path section of the output is blank. What am I missing? I would love to get some feedbacks or suggestions or even answer to this nightmare. I just can't seem to figure out what is causing the paths from displaying anything. I'm still fairly new to Python and I could really use some help!
Output of my current code
class Graph:
def minDistance(self, dist, queue):
# Initialize min value and min_index as -1
minimum = float("Inf")
min_index = -1
# from the dist array,pick one which
# has min value and is till in queue
for i in range(len(dist)):
if dist[i] < minimum and i in queue:
minimum = dist[i]
min_index = i
return min_index
def printPath(self, parent, j):
# Base Case : If j is source
if parent[j] == -1:
print()
j,
return
self.printPath(parent, parent[j])
print()
j,
def printSolution(self, dist, parent):
src = 0
print("Vertex \t\tDistance from Source\tPath")
for i in range(1, len(dist)):
print(("\n%d --> %d \t\t%d \t\t\t\t\t" % (src, i, dist[i])), end=' ')
self.printPath(parent, i)
def dijkstra(self, graph, src):
row = len(graph)
col = len(graph[0])
dist = [float("Inf")] * row
parent = [-1] * row
dist[src] = 0
queue = []
for i in range(row):
queue.append(i)
while queue:
u = self.minDistance(dist, queue)
queue.remove(u)
for i in range(col):
if graph[u][i] and i in queue:
if dist[u] + graph[u][i] < dist[i]:
dist[i] = dist[u] + graph[u][i]
parent[i] = u
self.printSolution(dist, parent)
g = Graph()
graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
]
g.dijkstra(graph, 0)
The basic issue with your code is that the printPath method is only outputting blanks and secondly, the printSolution method is not including the results of the printPath method. To fix these problems:
1 rewrite the printPath function as below:
def printPath(self, parent, j, l):
# Returns a list from destination to source
# Base case when j = source
if parent[j] == -1:
return l
else:
l.append(j)
return self.printPath(parent, parent[j], l)
Then rewrite the printSolution method as follows:
Note: I used the f format structure to simplify my print statement
def printSolution(self, dist, parent):
src = 0
print("Vertex \t\tDistance from Source\tPath")
for i in range(1, len(dist)):
st = f"\n{src} --> {i}\t\t{dist[i]}\t\t\t\t\t{self.printPath(parent,i,[])[::-1]}"
#print(("\n%d --> %d \t\t%d \t\t\t\t\t" % (src, i, dist[i])), end=' ')
#self.printPath(parent, i)
print (st)
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 2 years ago.
I'm trying to make the input maze of Astar algorithm(alogorithm to find the shortest path between start and destination and there can be some blockages within the maze,
which takes input a maze representing blockages only, as shown below).
From the GUI using the Click1 command in each button,
I intend to get an output like this(where I inserted a blockage at [3][2]).
1 represents blockage which is to avoided to find the path from start to end.
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
but I get a output as following,I can't understand why it's blocking the same column of each and every row
[[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
I created the maze in the init(): of class App() using this:
def __init__(self, master,dimension,indexes):
self.maze=[[0]*self.dimension]*self.dimension
this entire thing is within a class App():
for creating the grid of buttons, and storing their reference
self.gid = []
for i in range(self.dimension):
row = []
Grid.rowconfigure(self.frame1, i + 1, weight=3)
for j in range(self.dimension):
Grid.columnconfigure(self.frame1, j + 1, weight=3)
btn=Button(self.frame1,command=lambda i=i, j=j: self.Click1(i, j))
btn.grid(sticky=N+S+E+W,padx=2,pady=2,ipadx=1,ipady=1)
row.append(btn)
row[-1].grid(row=i + 1, column=j+1)
self.gid.append(row)
the Click1 method/Command that also within this class:
def Click1(self, i, j):
self.indxes.append((i,j))
if len(self.indxes)==1:
self.gid[i][j]["bg"]="blue" #indicates start
elif len(self.indxes)==2:
self.gid[i][j]["bg"]="green" #indicates destinations
else:
self.gid[i][j]["bg"] = "black"
self.maze[i][j] = 1 #how I insert blockage within the maze
Try this in your init:
def __init__(self, master,dimension,indexes):
self.maze = [[0] * self.dimension] for _ in range(self.dimension)]
The latter * self.dimension call was assigning the same reference to all your inner lists (dimension number of times) - meaning when one is changed all will change.
This creates a unique list for each sublist
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
B = 9
I want to find out the distances between the index[9] (B) and each of it's closest's 1's. For example, If we look at list A, we see that index 9 is this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
^
I would like to figure out the distances between B(index 9) and it's nearest 1's. For example, the nearest 1's in this case would be this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
^ ^
So in this case the output would be:
>> [2, 3] ##Since the distance between 1, 0, B is 2 and the distance between B, 0, 0, 1 is 3.
So far I've come up with the following code:
def checkDistance(A, B):
for i in A:
if i == 1:
#Check if it is the closest to B
#Check distance
Sadly I'm a beginner in python and I am struggling to finish. Any help would be much appreciated :)
def distance(lst,index):
c=[i for i,j in enumerate(lst) if j==1]
for k,l in zip(c[:-1],c[1:]):
if k < index < l:
return [index-k, l-index]
a = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
b = 9
distance(a, b)
Out: [2, 3]
You could use the following function. In this case, to make the function more abstract, you needn't force the value for the comparison to be 1 in the function.
In the function below, you do a for loop starting at the position you specified (in Python indexes start at 0, not at 1) and finishing when the list finishes.
The if statement compares element with the value of the list at a given position i
def checkDistance(lst,index,element):
counter = 0
results = []
for i in range(index,len(lst)):
if lst[i] == element:
print("Detected element at distance: " + str(counter))
results.append(counter)
counter += 1
return results
I found this code online and would really like for someone to explain it simply. I understand most of the initialisation of nodes, but don't understand as much once I get further down. If someone can explain the code near line by line, I would be grateful. The areas I find the most confusing are the calculation sections.
Thanks for any/all responses
class Node():
def __init__(self, parent=None, position=None):
self.parent = parent
self.position = position
self.g = 0
self.h = 0
self.f = 0
def __eq__(self, other):
return self.position == other.position
def astar(maze, start, end):
"""Returns a list of tuples as a path from the given start to the given end in the given maze"""
# Create start and end node
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0
# Initialize both open and closed list
open_list = []
closed_list = []
# Add the start node
open_list.append(start_node)
# Loop until you find the end
while len(open_list) > 0:
# Get the current node
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index
# Pop current off open list, add to closed list
open_list.pop(current_index)
closed_list.append(current_node)
# Found the goal
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1] # Return reversed path
# Generate children
children = []
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]: # Adjacent squares
# Get node position
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])
# Make sure within range
if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] > (len(maze[len(maze)-1]) -1) or node_position[1] < 0:
continue
# Make sure walkable terrain
if maze[node_position[0]][node_position[1]] != 0:
continue
# Create new node
new_node = Node(current_node, node_position)
# Append
children.append(new_node)
# Loop through children
for child in children:
# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue
# Create the f, g, and h values
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + ((child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h
# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
# Add the child to the open list
open_list.append(child)
def main():
maze = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
start = (0, 0)
end = (7, 6)
path = astar(maze, start, end)
print(path)
if __name__ == '__main__':
main()
I suggest you first understand the A* algorithm itself, here is a good video i found, check here. After understanding this, try to code it yourself in whatever language you want and then if you can't understand something ask about that stuff on SO.
I'm trying to create a game board using lists, but when I'm printing the board it prints way too many lists.
from random import randint
import pprint
class Gameboard:
def __init__(self, rows, columns):
self._rows = rows
self._columns = columns
self._board = []
for i in range(rows):
row = [0] * columns
self._board.append(row)
def drawBoard(self):
for i in range(self._rows):
for j in range(self._columns):
pprint.pprint(self._board)
Main program:
from gameboard import Gameboard
import pprint
def main():
myObject = Gameboard(7, 7)
myObject.drawBoard()
main()
My goal is to create a board that consists of (in this case) 7 lists with 7 elements within a list.
When I run the program now, it prints about 7*49 lists or something. What must I change to only print out one list with 7 lists within?
You could use an inline for loop to generate a list of "[]" strings and then iterate that print function however many times you needed, like the below:
import pprint
for i in range(7):
pprint.pprint(["[]" for j in range(7)])
By using .join() on the list you could also concatenate every element in the list into one long string, which looks arguably better.
import pprint
for i in range(7):
pprint.pprint(' '.join(["[]" for j in range(7)]))
Keep it simple:
def drawBoard(self):
print(*self._board, sep='\n')
OUTPUT
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]