Civilization IV/Python Debugging
Everybody has to do debugging when their scripts don't work, as it is so easy to make one little mistake, causing the whole code to make no sense. The first step in debugging is to switch the in-game debugging options on. To do this, open up Civilization4.ini (make sure to back it up), and change the following entries to the following values:
HidePythonExceptions = 0 ShowPythonDebugMsgs = 1 LoggingEnabled = 1 MessageLog = 1
This should enable in-game python popups, and cause all errors and messages to be printed in your My Documents/My Games/Civilization 4/Logs directory. The three important logs to look for when debugging are PythonDbg, PythonErr and PythonErr2.
 Common error messages and their causes
In the logs usually the errors will have a traceback on them. This traceback lists all the files that are effected by the error, and the lines the error occur on. The last line is usually the one you are interested in, as this is the one where the error occurs. Sometimes you'll have to go back a few steps as the error won't be on the last line, but usually it is!
 Syntax errors
These are mainly typing errors - missed ":"s, incorrect whitespace, or bad bracketing. The game usually picks up on these when you load it up. The error logs should show you exactly where the error is in the syntax with a little ^ symbol underneath it.
 Type Errors
If you try to use a function designed for a pointer on an integer value, you will get a type error. Go to the line specified and check that the function you're are using is valid. Usually it will say what type of function it is expecting, and what you've given it. NOTE: Some classes need () after them in functions, some don't. If you are getting a Type Error this may be the cause.
 Argument errors
These either occur when you are passing a function too many, or too few arguments. You have to make sure the amount of arguments you are passing a function matches the amount of arguments it takes, or the function will throw up an error when you try to run it.
 Name Errors
This means that you've tried to use something that the game doesn't know what is. For example, if you were to type a = b without first saying what b was, there is no way the computer could set a value to a. Remember a=b does not do the same as b=a. Also, make sure you haven't any "==" where you want "=", or vice versa.
Sometimes you'll get "Argument referenced before assignment". It's unclear whether this goes alongside the Name Error, if it needs its own category, but basically it's like a name error, but you define "a" later on in your code.
 "List index out of range"
This happens when you try and reference an index in a list, tuple, or dictionary which doesn't exist. This one can be tough, and you might have to use methods described in the next part of this section to see exactly what is going wrong.
 Code not behaving
So you've written your code. It all functions with no errors... but it doesn't actually produce the results you expect it to in the game. There can be several causes of this:
Firstly, if you think a piece of code should be having an effect in the game, make sure that it is by checking the API to see if it is a VOID function. It's quite a common mistake when first starting out to use other functions thinking that they will do something, when in fact they just retrieve information.
Secondly, if everything seems right you need to start putting debug messages in. This section brings you back right to the very start of python coding, when you were telling your computer to print "hello world". What you will need to do is to get the computer to print a message telling you what a certain value is at a certain point in the code, and compare it to what you think it should be. For example, the following code will print "a=b" in the debugging log if a=b, and print the values of a and b otherwise:
if a == b: print "a=b" else: print a print b
This can be quite hard to decipher in the debug log (often you will have many many numbers), so you can do more advanced messages
if a == b: print "a = b, a and b are %d, and %d"%(a,b)) else: print("a = %d"%(a)) print("b = %d"%(b))
Where %d will reference the number outside the "" after the %. If you want to place a string there you have to use %s. This can give you detailed information as to exactly what is going on inside your code, and hopefully from that you should be able to see what is going wrong with it.