I am reading through "Making games with Python & Pygame" and I have noticed that because the author uses lots of functions with drawing in to break his code up, he uses lots of globals  such as GRIDSIZE or BACKGROUNDCOLOR. I was always told that globals were generally bad, but without them, every drawing function would have ten more, repeating parameters - and I have also been told that repetition is bad. I wondered, then, is the author is correct in using globals for parameters that appear in most (drawing) functions, or should have just used more, repetitive parameters.
Constant globals can be OK, despite whatever general warnings you may have heard.
In Python "constant" means "named in capital letters as a hint that nobody should modify them", and "globals" means "module-level variables", but the principle still applies. So hopefully GRIDSIZE and BACKGROUNDCOLOR are constant for the duration of the program, but it's possible they are not: I haven't seem the code.
There are plenty of examples of module-level constants in the standard Python libraries. For example errno contains E2BIG, EACCESS, etc. math contains math.pi.
However, those examples are even more constant than GRIDSIZE. Presumably it could change between different runs of the same program, which math.pi will not. So you need to assess the consequences of this particular global, and decide whether to use it or not.

I was always told that globals were generally bad

Bad things are bad for reasons, not "generally bad". In order to decide what to do you need to understand the reasons. Using globals (or, in Python, module-scope objects) causes certain problems:

dependencies on previously-executed code: this is the worst problem, but it applies only to mutable globals.

If you use a global that can be modified elsewhere, then in order for someone reading the code to reason about its current value they might need to know about the whole program, because any part of the program might access the global. If you keep your mutables in an object that only parts of your code ever get to see, then you only have to reason about those parts of your code that interact with that object.
This might not sound like a big difference if your program is one file that's 100 lines long, but it becomes one eventually. Making your code easy to work with is almost all about making it easy for a reader to reason about what the code does. What else can affect it is a big part of that, so this is important. And "a reader" is you, next time you want to change something, so helping out "readers" of your code is pure self-interest. 

dependencies on concurrently-executing code: mutable globals + threads = needs locks = effort.
hidden dependencies: this is applicable even for constants.

You have to decide whether it's OK for this bit of code to have some dependencies that are not supplied as parameters ("injected") by the caller of that code.
Almost always the answer to this question is "yes". If it is "absolutely not" then you're in a tight spot if you dislike lots of parameters, because you wouldn't even use Python builtins by name, let alone names from modules the code imports. Having decided that it's OK to have hidden dependencies, you have to think about the consequences of GRIDSIZE being one of them, on the way you use and especially test the code. Provided that you don't want to draw on different-sized grids in the same program you're basically fine until you want to write tests that cover lots of different values of GRIDSIZE. You'd do that to give yourself confidence now that when you change GRIDSIZE later nothing will break.
At that point you'd probably want to be able to provide it as a parameter. For this reason you might find it more useful to have parameters with defaults rather than global values. To prevent long repetitive parameter lists you might pass around one object that combines all of these settings rather than each separately. Just beware of creating an object with multiple unrelated purposes, because the others are distracting if you want to reason about just one.

namespace pollution: relevant in C, if you don't use static then two completely unrelated files cannot have different functions of the same name. Not so relevant in Python where everything is in namespaces.
Globals vs Parameters for Functions with the Same Parameters