Battleships game in Python
Your program is pretty good, imports at the top, some functions and comprehensions.
But they can all be improved.


To adhere to PEP8 you should only import one module per import.
You need some more functions, the ones your are using I would not use and would infuriate me.
This is more an unwritten notion, but _ is known as the throw away variable.
Since you throw away the range's items you could do:

[' ' for _ in range(gridSize)]



I'd change the way you display the rows, currently you display two characters per print,
this is quite hard to read, and not very efficient.
Instead I'd recommend a list comprehension!

You display a space if getGrid(x,y) is "C", otherwise getGrid(x,y), for each character in that row.
So:

row = [" " if getGrid(x, y) == "C" else getGrid(x, y) for y in range(gridSize)]


To then display this row you should use ' '.join(row). This puts a single space in-between each position on the board.

The other major change I'd make is the use of str.format.
Take the following line:

print(" " + result + " [Ships: " + str(ships) + ", Size: " + str(gridSize) + ", Hits: " + str(hits) + "]\n")


That's hard to read with all the string concatenations and conversion, which str.format tidies up.
The equivalent would be:

print(" {} [Ships: {}, Size: {}, Hits: {}]\n".format(result, ships, gridSize, hits))


You can now tell the format of the string, and can reasonably guess what will go there.
All in little to no time.



For a few additional changes I'd recommend you change range with enumerate to get the x positions and the row, where you display the grid.
And I'd completely remove the range when using the row comprehension.
To show this:

for x, row in enumerate(game):
    print(' {} {}'.format(x, ' '.join([" " if y == "C" else y for y in row])))


I would also change the boards variable name to board so that people can instantly understand what you mean when you reference it.

In Python you should use snake_case not pascalCase for functions and variables, so gridSize should be grid_size.

And finally, you should use a try-except block when you are converting user input to a number as CAD97 put in their answer.
This is as your program will crash if I enter "a".

To improve the xLabel creation you can think of it like we did the row, however you display the item you get from the range. This means that the list comprehension that you'd do is:

row = [str(i) for i in range(gridSize)]
xLabel = " " * 3 + " ".join(row)