Jump to content
Registration disabled at the moment Read more... ×
Jacek Laskowski

TypeError: 'PythonDelphiVar' object cannot be interpreted as an integer"

Recommended Posts

My code in Delphi:


 

procedure TForm1.btnRunClick(Sender: TObject);
var
  PyEngine: TPythonEngine;
  PyHeight: Integer;
  PyIO: TPythonGUIInputOutput;
  PyModule: TPythonModule;
  PyWidth: Integer;
  VarHeight: TPythonDelphiVar;
  VarWidth: TPythonDelphiVar;
begin
  PyWidth := 80;
  PyHeight := 40;

  PyEngine := TPythonEngine.Create(nil);
  PyModule := TPythonModule.Create(nil);
  PyIO := TPythonGUIInputOutput.Create(nil);
  try
    PyIO.Output := mmoLog;
    PyEngine.IO := PyIO;
    PyEngine.DllName := 'python38.dll';
    PyEngine.DllPath := ExtractFilePath(Application.ExeName) + 'python\';
    PyEngine.UseLastKnownVersion := False;
    PyEngine.AutoLoad := False;
    PyEngine.AutoUnload := False;
    PyModule.Engine := PyEngine;
    PyModule.ModuleName := '__main__';
    try
     PyEngine.LoadDll;
    except
      on E: Exception do
      begin
        ShowMessage('Error at load Python: ' + E.Message);
        Exit;
      end;
    end;

    PyModule.Initialize;
    PyEngine.PyRun_SimpleString('import builtins; __builtins__ = builtins');

    VarWidth := TPythonDelphiVar.Create(nil);
    VarWidth.Engine := PyEngine;
    VarWidth.Module := '__main__';
    VarWidth.VarName := 'WIDTH';
    VarWidth.Initialize;
    VarWidth.Value := PyWidth;

    VarHeight := TPythonDelphiVar.Create(nil);
    VarHeight.Engine := PyEngine;
    VarHeight.Module := '__main__';
    VarHeight.VarName := 'HEIGHT';
    VarHeight.Initialize;
    VarHeight.Value := PyHeight;

    PyEngine.ExecStrings(mmoSource.Lines, '__main__');

  finally
    VarWidth.Free;
    VarHeight.Free;
    PyIO.Free;
    PyModule.Free;
    PyEngine.Free;
  end;
end;

And python script:

 

canvas = [[' ' for _ in range(WIDTH)] for _ in range(HEIGHT)]

 

After run this I get an error:

 

Traceback (most recent call last):
  File "__main__", line 1, in <module>
TypeError: 'PythonDelphiVar' object cannot be interpreted as an integer

 

I want to pass two variables WIDTH and HEIGHT to the script. What am I doing incorrectly?

 

 

Share this post


Link to post
31 minutes ago, Jacek Laskowski said:

VarWidth.Initialize;

VarWidth.Value := PyWidth;

Does reversing the order help?

 

    VarWidth.Value := PyWidth;
    VarWidth.Initialize;

 

Share this post


Link to post
14 minutes ago, pyscripter said:

Does reversing the order help? 

 


    VarWidth.Value := PyWidth;
    VarWidth.Initialize;

 

No, then I get an error on assignment line:

 

VarWidth.Value := PyWidth; <-- here I get an error
VarWidth.Initialize;

 

Error message:

 

ThreadId=4800
ProcessId=38
ThreadName=""
ExceptionMessage="No variable was created"
ExceptionName="Exception"
ExceptionDisplayName="Exception"
ExceptionAddress=751DC5AF
FileName=<not available>
LineNumber=<not available>
ExceptionObject=033BE960
Classes=[Exception,TObject]

 

Error is raised here:

 

procedure TPythonDelphiVar.SetValue( const val : Variant );
begin
  if Assigned( FVarObject ) then
    with TPyVar(PythonToDelphi(FVarObject)) do
      SetValueFromVariant(val)
  else
    raise Exception.Create(SVarNotCreated); <-- here
end;

 

 

--- edit

 

When I change the python script to:

 

print(HEIGHT, WIDTH)

 

then all run ok, and in the log I get:

 

<PythonDelphiVar: 40> <PythonDelphiVar: 60>

 

Edited by Jacek Laskowski
adding

Share this post


Link to post
canvas = [[' ' for _ in range(WIDTH)] for _ in range(HEIGHT)]

needs to be

canvas = [[' ' for _ in range(WIDTH.Value)] for _ in range(HEIGHT.Value)]
  • Thanks 1

Share this post


Link to post
10 hours ago, pyscripter said:

canvas = [[' ' for _ in range(WIDTH)] for _ in range(HEIGHT)]

needs to be


canvas = [[' ' for _ in range(WIDTH.Value)] for _ in range(HEIGHT.Value)]

Thanks! This was the cause of the problem.

 

By the way, I have a question. This script in Python is quite a bit bigger, here I have given a minimal causing the error, the script uses WIDTH and HEIGHT variables. Before I passed these variables from Delphi they were defined at the beginning of the script by a simple assignment:

HEIGHT = 40
WIDTH = 60

However, when I added these two variables (TPythonDelphiVar) from the Delphi side, and the module (TPythonModule) object it stopped working many keywords including “import” and only adding a line in the Delphi code:

 

PyEngine.PyRun_SimpleString(‘import builtins; __builtins__ = builtins’);

...resulted in correct working. What is the result of this?

 

Why is it that without variable and module objects, the contents of “builtins” are automatically available, but disappear after adding them?

 

Edited by Jacek Laskowski

Share this post


Link to post
4 hours ago, Jacek Laskowski said:

HEIGHT = 40

WIDTH = 60

The above should also be:

HEIGHT.Value = 40
WIDTH.Value = 60

You should not need to import builtins.   Not sure what the problem was.

Share this post


Link to post

Probably my English is too poor, that's why you misunderstood me.


Again from start.

In the beginning I had a self-contained script, without external variables. I had a simple script to just run P4D, I'm using it for the first time and learning. In that simple script there were only python variables set up as you do in python:

HEIGHT = 40
WIDTH = 60

And then, once everything started working, I decided to learn how to pass variables from Delphi. Then I removed the setting of these two variables from the beginning of the script and added to the delphi code the use of TPythonDelphiVar with these two variables. Well, this is where the problems started, because I didn't know that after this change I had to add .Value to these variables.

 

At the same time, it turned out that I also need to add a line of code with:

PyEngine.PyRun_SimpleString(‘import builtins; __builtins__ = builtins’);

Because without this line I got errors:

Traceback (most recent call last):
  File "__main__", line 1, in <module>
ImportError: __import__ not found

The above error comes from a script that starts with a line:

 import math

 

When I use another script, such as:

result = sum(i * i for i in range(1, 11))
print("Suma kwadratów od 1 do 10 to:", result)

 

I get a different error:


Traceback (most recent call last):
  File "__main__", line 1, in <module>
NameError: name 'sum' is not defined

In both cases, the very first word of the script is problematic.

When I add a delphi line code with "builtins" it all works.

 

What is the problem?

Edited by Jacek Laskowski

Share this post


Link to post

Here the following runs fine (without  importing builtins):

procedure TForm1.Button1Click(Sender: TObject);
var
  PyEngine: TPythonEngine;
  PyHeight: Integer;
  PyIO: TPythonGUIInputOutput;
  PyModule: TPythonModule;
  PyWidth: Integer;
  VarHeight: TPythonDelphiVar;
  VarWidth: TPythonDelphiVar;
begin
  PyWidth := 80;
  PyHeight := 40;
  PyEngine := TPythonEngine.Create(nil);
  PyModule := TPythonModule.Create(nil);
  PyIO := TPythonGUIInputOutput.Create(nil);
  try
    PyIO.Output := Memo1;
    PyEngine.IO := PyIO;
    PyEngine.UseLastKnownVersion := True;
    PyEngine.AutoLoad := False;
    PyEngine.AutoUnload := False;
    PyModule.Engine := PyEngine;
    PyModule.ModuleName := '__main__';
    try
     PyEngine.LoadDll;
    except
      on E: Exception do
      begin
        ShowMessage('Error at load Python: ' + E.Message);
        Exit;
      end;
    end;

    PyModule.Initialize;
    //PyEngine.PyRun_SimpleString('import builtins; __builtins__ = builtins');

    VarWidth := TPythonDelphiVar.Create(nil);
    VarWidth.Engine := PyEngine;
    VarWidth.Module := '__main__';
    VarWidth.VarName := 'WIDTH';
    VarWidth.Initialize;
    VarWidth.Value := PyWidth;

    VarHeight := TPythonDelphiVar.Create(nil);
    VarHeight.Engine := PyEngine;
    VarHeight.Module := '__main__';
    VarHeight.VarName := 'HEIGHT';
    VarHeight.Initialize;
    VarHeight.Value := PyHeight;
    var Source := '''
import math
result = sum(i * i for i in range(1, 11))
print("Suma kwadratów od 1 do 10 to:", result)
canvas = [[' ' for _ in range(WIDTH.Value)] for _ in range(HEIGHT.Value)]
print(canvas)
''';
    PyEngine.ExecString(Utf8Encode(Source), '__main__');
  finally
    VarWidth.Free;
    VarHeight.Free;
    PyIO.Free;
    PyModule.Free;
    PyEngine.Free;
  end;
end;

 

However you should not call the module '__main__', since by doing that you will be overriding the default python module with the same name.

Call the module something else say my_module and then add to your python script:

 

from my_module import WIDTH, HEIGHT

Share this post


Link to post

@pyscripter

Thanks, it works.


Still a question about that module name. Should I change the module name in the TPythonDelphiVar and TPythonModule components? That is, should it be like this:

 

    PyModule.Engine := PyEngine;
    PyModule.ModuleName := 'my_name';  <-- here
    [..]    
    VarWidth := TPythonDelphiVar.Create(nil);
    VarWidth.Engine := PyEngine;
    VarWidth.Module := 'my_name';  <-- here
    [...]

Or only in variable objects?

Share this post


Link to post

Actually for this use case the TPythonModule is not needed.  You can directly import the variables into the '__main__' module.

 

e,g,

 

procedure TForm1.Button1Click(Sender: TObject);
var
  PyEngine: TPythonEngine;
  PyHeight: Integer;
  PyIO: TPythonGUIInputOutput;
  PyWidth: Integer;
  VarHeight: TPythonDelphiVar;
  VarWidth: TPythonDelphiVar;
begin
  PyWidth := 80;
  PyHeight := 40;
  PyEngine := TPythonEngine.Create(nil);
  PyIO := TPythonGUIInputOutput.Create(nil);
  try
    PyIO.Output := Memo1;
    PyEngine.IO := PyIO;
    PyEngine.UseLastKnownVersion := True;
    PyEngine.AutoLoad := False;
    PyEngine.AutoUnload := False;
    try
     PyEngine.LoadDll;
    except
      on E: Exception do
      begin
        ShowMessage('Error at load Python: ' + E.Message);
        Exit;
      end;
    end;

    VarWidth := TPythonDelphiVar.Create(nil);
    VarWidth.Engine := PyEngine;
    VarWidth.Module := '__main__';
    VarWidth.VarName := 'WIDTH';
    VarWidth.Initialize;
    VarWidth.Value := PyWidth;

    VarHeight := TPythonDelphiVar.Create(nil);
    VarHeight.Engine := PyEngine;
    VarHeight.Module := '__main__';
    VarHeight.VarName := 'HEIGHT';
    VarHeight.Initialize;
    VarHeight.Value := PyHeight;
    var Source := '''
import math
result = sum(i * i for i in range(1, 11))
print("Suma kwadratów od 1 do 10 to:", result)
canvas = [[' ' for _ in range(WIDTH.Value)] for _ in range(HEIGHT.Value)]
print(canvas)
''';
    PyEngine.ExecString(Utf8Encode(Source), '__main__');
  finally
    VarWidth.Free;
    VarHeight.Free;
    PyIO.Free;
    PyEngine.Free;
  end;
end;


 

Share this post


Link to post

@pyscripter

And if I just want to pass a string to a Python script is this way:

var
 pObj: PPyObject;
 data: string;
[...]
 data := 'some long string';
 pObj := fPyEngine.PyUnicode_FromString(PAnsiChar(data));
 fPyModule.SetVar('data', pObj);

...sufficient and correct?

Share this post


Link to post

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×