Is there any helpful debug tools to accelerate C-Python debug?

a mistake can take me hours to debug, focus and fix.
It just like a nightmare…
is there any runing params can always show the error line number.

gcc’s error msg is too simple. so do the python…

Step 1: Remove any “except: pass” that you have in your code. Step 2: Run your code again and look for the exception.

This solves most problems. If you still have issues, insert “print” calls in strategic places. Figure out what your code is doing.

Without seeing your code, there isn’t really anything more we can advise.

That only helps with syntax errors, it is not going to help with runtime bugs in your C code.

shareing some infos what I got:

if you invoke c-python interface again & again.
because the garbage collection is not executed.
the variables defined in several independent file, is shared by each other
some variable defined in another .py file can break the current .py file 's scirpts processing.

for example:
you define a variable named “min” is a python file, in that place is runing well.
and In another .py files, you need call the system-function min(data_array);
then the exception triggered;

python can not report the last exception’s line number, and calling stack?

Why are you running unrelated python code in the same python?
It is expected that you would run two programs like this:

python prog1.py
python prog2.py

If prog1.py does

def min(a,b):
     …

That min will not be seen by prog2.py.

Not sure exactly how you broke builtin min, you would have to share source code for us to figure that out.

I do know how to do it, but I would be surprised if you accidentally hit on the way to do this.

In my latest project, I use python to do some calc work.
the sample data will be coming in every 5 secs~1 mins.
then I passed the data to python throught Python-C API.

I don’t want start a python exec environment every times. I think there will be spent more times.
so I init the python exec object in my app start routine.
then everytime, I just feed data in, calc by python, then took the result away.

it is very easy to hide the system built in functions:

min = 3

then “min” is an integer now.

my partner suggest a debug method to me:

void *ret = PyRun_File(file, py_sh_filename, Py_file_input, pDict, pDict);
if(ret ==NULL) 
{
    PyErr_Print();
    printf(".py invoke error %s\n", py_sh_filename);fflush(stdout);
    fclose(file);
    exit(0);
}

PyErr_Print() can print the line numer when exception occur.

thank you all. bro.

There is always a way to break things. This is especially easy in a language like Python that has a basic philosophy of “a name is just a name”: you have almost total freedom to attach any value to any name.
In earlier versions of Python you could even do:

False = True

The only answer to that is: Don’t do that. Don’t use builtin function names as variable names, since you’re going to make a lot of trouble for yourself.

It’s not clear to me, btw, why you’re using Python C APIs if you just want to execute some Python scripts. Doing so seems, in almost any kind of scenario, a huge overkill. Why don’t you use the Python interpreter?

With the qualifier that, if you didn’t know you were shadowing a builtin, it probably doesn’t matter :slight_smile: For example, if you use the name super or getattr in your code, you’re probably going to run into problems somewhere, but reusing id is only sometimes a problem, and replacing the ones intended for interactive work (quit, copyright, etc) is almost certainly fine.

But if you’re curious as to why the language lets you do this… the main reason is that it is perfectly reasonable to do something like this:

_print = print
def print(*args, **kwargs):
    kwargs["flush"] = True
    return _print(*args, **kwargs)

Technically, this is shadowing the builtin, just like print = 1 would be. But it’s shadowing it with something that’s intended to achieve the same goal, and that is incredibly useful - so useful, in fact, that one of the breaking changes in Python 3.0 was changing print from a language keyword into a builtin function.

1 Like

Ok i see why you have problems.
Using PyRun_File is make the environment inside python a mess that is hard to reason about.

I suggestion you do not use this function to load the same code multiple times.
Or worse changed code as that will inherit stuff from previous run calls.

Load your code once and then call a function you have loaded with your data.

Totally agree with @Rosuav - But I would add the caveat, we’re talking to people here who are either beginners or not very familiar, apparently, with Python. To those I simply say: Just don’t do that (which implies: learn about Python builtins).

It’s not just a question whether or not the code works fine, btw, when you shadow a variable name (unintentionally or deliberately) - it can also hurt readability.

1 Like

Very fair consideration. And if you have an editor that colours every Python builtin, then I would definitely agree - if you see that colour show up, pick a different name. But it’s also not going to bite you if you happen to say “quit = False; while not quit: … quit = True”.

Neither answer is wrong, and part of the beauty of Python is that you can go ahead and do things that you might change later. (But regret nothing and go with it!)

1 Like

It took me triple times to grasp what your meaning.
For my problem, I found another solutions.
even I still using a single python-c environment again and again.

python’s object has reference - counter
so when I created the python exec environment in C.
I add the reference counter,

//step 1.add reference counter to the only two object what I using to invoke .py script files.
Py_Initialize();
pModule = PyImport_AddModule(“main”);
pDict = PyModule_GetDict(pModule);
Py_INCREF(pModule);
Py_INCREF(pDict);

//step 1.deference related py object
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pDict); // 释放pDict对象的引用
Py_DECREF(pModule); // 释放pModule对象的引用
Py_Finalize();

//Step3.after every python invoke, exec gargdge-collection procedure.
onst char *pyFileResetEnvironment = “./py/garbdge_collect.py”;
void ResetPyEnvironment(void)
{
InvokePythonFile(pyFileResetEnvironment);
}

btw, I using C-python API, the intention is if python exec speed is not fast enough, I could replace the .py calc routine with manual-tuned C code.

Hi 旭辉(?),

释放 seems a misleading translation for the behavior of DECREF. A more correct translation is:
减少X对象引用的数量 The reference is not necessarily freed, it’s just the reference count that is decreased. So, at that point, you do not know whether or not the ref count actually becomes 0.

thank you. the concept of reference couter. I know what that mean.
it seemed that I have not code in C for too much time,
the memory leak or segment faults seems more often.
that’s my own problem. thank u all. all of u.
have a nice day.