Jump to content
softtouch

MainModule.varname is cached?

Recommended Posts

When you access a Python variable or constant through MainModule.varname, Python4Delphi retrieves the value and caches it I think.

Subsequent executions of Python scripts, even if they don't define the same variable, won't automatically clear this cached value and MainModule.varname retun the previous value.

is there any function that clears this cached values without reinitializing the python engine?

 

Example:

python1.py:

MYVALUE = 'test'

 

Delphi:

python.ExecFile(python1.py);

s:=MainModule.MYVALUE; // This return 'test'

 

python.ExecFile(python2.py); // This does not have this constant/variable in it

s:=MainModule.MYVALUE; // This return again 'test'

 

Edited by softtouch

Share this post


Link to post

Indeed.   Python variables are reference counted.   As long as you keep a reference the python object it refers to is kept alive.

When you have a statement like:

 

var s:Variant :=MainModule.MYVALUE 

 

s is a custom variant that stores the python reference.   The variable will be dereferenced, when s goes out of scope or you explicitly clear s (VarClear(s)).

 

Edited by pyscripter

Share this post


Link to post

I still encounter the problem.

 

Python script python1.py:

VALUE = 'testing'

Python script python1.py:

MYVAL = 'something else'

 

Delphi:

var val:variant;

GetPythonEngine.ExecFile('python1.py');
val := MainModule.VALUE;
// val contains 'testing'

varclear(val);
// val shows "unassigned"

GetPythonEngine.ExecFile('python2.py');
val := MainModule.VALUE;
// val contains 'testing' again, even it does not exist in python2.py.

 

Share this post


Link to post
41 minutes ago, softtouch said:

val contains 'testing' again, even it does not exist in python2.py.

Of course it does.

 

What you are doing is like running the following python script:

exec("a = 1; print(a)")
exec("b = 1; print(a)")

a is created in the first statement and still exists when the second statement is executed.

 

but if you do

exec("a = 1; print(a)", {}, {})
exec("b = 1; print(a)", {}, {})

then the second statement raises an error.

 

ExecFile has the following signature:

 

    procedure  ExecFile(const FileName: string; locals: PPyObject = nil; globals: PPyObject = nil); 

 

If you provide no arguments for locals and globals, the code is executed in the namespace of the __main__ module.    If you do not want this to happen then you should provide empty dictionaries as arguments for the locals and globals parameters (or just the locals).  But then MainModule.VALUE will raise an error.

 

Example code (not tested):

var Py := GetPythonEngine;
var NewDict := NewPythonDict;
Py.ExecFile('python1.py', ExtractPythonObjectFrom(NewDict));
var val := NewDict.GetItem("VALUE");

NewDict := NewPythonDict;
Py.ExecFile('python2.py', ExtractPythonObject(NewDict));
val := NewDict.GetItem("VALUE");  // will raise an error since VALUE does not exist
VarClear(NewDict);

 

Edited by pyscripter

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×