Maximize the number of PyGame sprites, with collision detection
A quick suggestion. If you look at the implementation of spritecollide, you'll see that it iterates over all the sprites in the group to see if the rectangles overlap. This means that the loop:

for box in boxs:
    # ...
    touch = pygame.sprite.spritecollide(box, boxs, False)


takes time proportional to the square of the number of boxes.

What I would try instead would be to insert the boxes into a spatial index which can find intersections efficiently. For example, put them in an R-tree using the Rtree package, and then call the intersection method. Or put their centres in a kd-tree using scipy.spatial.KDTree and then call the query_pairs method, passing the size of the largest box as the search radius.

Responses to comments


There are ways to update spatial indexes as objects move (typically in games objects don't move very far in a frame, so updates tend to be local). But the simplest thing to do is to rebuild the spatial index each frame — this has cost \$\Theta(n\log n)\$ which is an improvement on the \$\Theta(n^2)\$ approach of comparing all pairs of objects.
Here's an example using scipy.spatial.KDTree. Using this data structure requires three steps. First, take your list of sprites and build a tree containing their centres:

from scipy.spatial import KDTree
tree = KDTree([sprite.rect.center for sprite in sprites])


Second, query the tree for candidate collisions, using an appropriate search distance (in this case the diameter of the largest sprite):

from math import hypot
distance = max(hypot(*sprite.rect.size) for sprite in sprites)
collisions = tree.query_pairs(distance)


Third, not all of the candidates are actually colliding (because we have only queried the distance between their centres), so check to see which ones are real:

for i, j in collisions:
    if sprite[i].rect.colliderect(sprite[j].rect):
        # handle collision between sprite[i] and sprite[j]