Popular C software is so reliable because of
enormous amount of effort spent developing, testing, and polishing it over many years - not because error handling in C is superior to that in higher-level languages.
If your python script sticks around for 30 years constantly being used by millions of people - I bet it will be rock solid as well. All other things [1] being equal [2], a program written in a higher-level language will likely be more reliable - simply because it will likely be shorter. C has many properties conductive to great longevity of software written in it, but error handling is not one of them.
Now, to the rant about not knowing the exact number of exceptions a function can throw. Most sane languages [3] give you exception hierarchy. You know that every function can throw an Exception (or Throwable, or whatever the root of all things evil is called in your language), and you either handle it or let in propagate. The important bit is you catch exceptions based on what you can handle in a current context, not on what the functions you call can throw [4]. As long as you realize that every call can potentially throw, it is not important what exactly is thrown - letting you abstract away the exact nature of an error is a feature, not a bug, that's what exceptions are there for! Let's say some function deep below changed and now throws a new exception type. So what? It didn't change what you can handle, so there's no reason to modify calling function - just let the exception propagate. What if nothing in your program can handle that exception? You let it crash (hopefully to the debugger, and no, it's not ironic that I suggest it in a topic about reliable programs - crashing is a reliability feature invented to expose problems that would be hidden and hard to debug otherwise). Of course you may also put a few catch-all clauses in a very limited number of strategic places.
If you approach exceptions this way they are vastly superior to error codes.
[1] Scope of the problem, amount of effort spent on development, programmer skills
[2] Or at least on the same order of magnitude
[3] With a notable exception of C++ - I'm not sure what they were smoking when they decided that throwing arbitrary values is a good idea
[4] And this, by the way, is what's wrong with checked exceptions in Java
PS. Didn't mean that having no exceptions is insane - but that if a language has exceptions, the sane thing to do is to organize them in a hierarchy with a single root.