This is not simply enforcing a style guide. It’s warning you that, assuming I’ve correctly guessed what the code looks like, it doesn’t mean what you appear to think it means.
If we have something like
counter_urls = 0
def some_function():
counter_urls += 1
this will fail at runtime:
From the linting tool’s perspective, counter_urls inside the function is a “redefinition” - because it is. Since the code has an assignment to counter_urls, and it does not have a global declaration, counter_urls must be a separate local variable. The tool warns you because people usually don’t want to make a local with the same name.
Then, from the tool’s perspective, the counter_urls outside the function is supposed to be a “constant” because there isn’t any code in the file that could change it.
You need to use the global declaration to make a global variable work the way you want it to.
The complaint is not about the syntax you use, or simply the fact that you have a global. (After all, in Python, the function is also a global variable.)
The problem is that you have code that wants to re-assign a name that wasn’t given to nor created by it. Doing things like that makes it harder to reason about the code - which is part of why Python has this design that requires the global statement. (Although the main reason for the design is that, this way, you don’t need any kind of declaration for local variables, which are much more common.)
There are many ways to manage scope. If you insist on re-assigning a global variable, then the global statement is the only correct way to make that work. But in almost every case, the right way to solve the problem is to give the function what it needs, instead of having the function take those things. That is: use arguments (in calls) and parameters (in the definition) to send information into the function, and use the return value to get information out.
Caveat: Python does allow you to modify the object in a global without this global declaration. (Assuming the object offers any ways to modify it. Many built-in types don’t.) The global name is a way to get at that object, and then whatever you do with it is not the name’s concern. But this is still a disorganized, complex way to program that will bite you in the long run.