Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

3 Neutral
  1. psla314

    Multiple Instances of Python Engine

    I have managed to get multiple modules (each with a different script) working simultaneously (run one at a time, but modules in memory at same time), but not sure its the most efficient way. I am creating multiple modules then when the script is changed and run, I am clearing vars and methods and Initalizing the module each time , then wrapping a few delphi classes and injecting into module via module.SetVar('Source', p) and module.SetVar('Output', p). To execute script I am locking the Engine and then using PythonModule.GetVar('__dict__') to get the local and passing that to the ExecString as local and global. (To have a clean namespace each time) Basic code is below. Question - Is there a more efficient way to doing this without having to Initialize the module each time the script changes ? And Ideally not have to wrap and insert the variables each time. m_sScript.LoadFromFile(sFilePath); m_PythonModule.ClearVars; m_PythonModule.ClearMethods; m_PythonModule.Initialize; datalist := TDatalist.create; // this is freed by python object pSource := m_PyDelphiWrapper.Wrap(datalist, WrapDelphi.soOwned); m_PythonModule.SetVar('Source', pSource ); m_PythonEngine.Py_DecRef(pSource); dataout := TDatalist.create; pDataOut := m_PyDelphiWrapper.Wrap(dataout, WrapDelphi.soOwned); m_PythonModule.SetVar('DataOut', pDataOut ); m_PythonEngine.Py_DecRef(pDataOut); // Run Process Method in Python SCript m_PythonEngine.Lock; try locals := m_PythonModule.GetVar('__dict__'); m_PythonEngine.ExecString(ansistring(m_sScript.DataString), locals, locals); m_PythonEngine.CheckError; pyfunc := m_PythonEngine.FindFunction(m_PythonModule.ModuleName , 'Process'); if assigned(pyfunc) then begin try m_PythonEngine.EvalFunction(pyfunc,[]); finally m_PythonEngine.Py_DecRef(pyfunc); end; end; m_PythonEngine.Py_DecRef(locals); finally m_PythonEngine.Unlock; end;
  2. psla314

    Multiple Instances of Python Engine

    I think we need multiple modules because we are injecting vars into the module for each script. Each script will have different data injected. So figured it would be better to inject data once and then swap modules/script to execute the script. Note the scripts will get execute multiple times after new data is added to the injected data objects.
  3. UPDATE - I found a fix/workaround. It appears the order of the packages matter now in project options. I changed the order of the packages from vcl;rtl;vclx -> rtl;vcl;vclx and the problem is solved. This worked fine in 10.2 so some changes must have been made to how packages are loaded/found.
  4. Hi Just installed Delphi 10.4 Update 2 - After a successful full Build of my project group with 10 sub projects, without any issues, I then try and compile any of the sub projects in the same session and I get this error: [dcc64 Fatal Error] Optuma.dpr(447): E2411 Unit Vcl.Forms in package vcl refers to unit System.Types which is not found in any package. Packaged units must refer only to packaged units one of the other sub projects gets a similar error [dcc64 Fatal Error] OPCM.dpr(23): E2411 Unit Vcl.StdCtrls in package vcl refers to unit System.Actions which is not found in any package. Packaged units must refer only to packaged units My project group consists of an exe project and a number of dll projects. All these projects have runtime packages turned on for vcl;rtl;vclx. This is to reduce the size of the exe and dlls. When I turn off the runtime packages the error does not occur, so it must be related to the runtime linked packages. Note sure how it can have a problem with Vcl.Forms referring to System.Types, seems like a bug to me. Am I missing something, or should I raise an issue ? This same project worked fine with Delphi 10.2 Regards Peter
  5. psla314

    Array of Objects

    Hi Is it possible to create an array of objects in Delphi and then have that available in the Python Script ? e.g. Where DataIn is pre defined in Delphi and added to the module using PythonModule.SetVar( 'DataIn', p ); x1 = DataIn[0].X y1 = DataIn[0].Y x2 = DataIn[1].X y2 = DataIn[1].Y I can get the following to work using 0 = X and 1 = Y and a DataInType : TPythonType x1 := DataIn(0,0); y1 := DataIn(0,1); x2 := DataIn(1,0); y2 := DataIn(1,1); p := DataInType.CreateInstance; Source := TPyDataList( PythonToDelphi(p) ); PythonModule.SetVar( 'Source', p ); PythonEngine.Py_DecRef(p); But am having trouble getting the array operator to work in Delphi4Python Is this even possible to use an array operator to call default index getters and setting like in Delphi ? Regards Peter
  6. psla314

    Multiple Instances of Python Engine

    Thanks for the advice, I'll try using multiple modules and pass through a single engine. Didn't know about the Python global interpreter lock.
  7. Hi We are looking at using the Python engine in a Delphi graphing application, so we would have a different python script for each chart, with multi charts opened at once. So in this case we would have different python scripts each with different python4delphi modules containing different input data for processing and producing different output data. I first tried this with with each chart having a separate python4delphi engine and module and script, but I got an exception There is already one instance of TPythonEngine running After examining the code there appears to be a global variable for the engine, not allowing more than one instance of the engine. My question is what is the best way of handing multiple scripts with multiple modules simultaneously? Is there a way to bypass the global engine variable so we can have multiple engine instances ? Or do we need to keep a list of all the scripts/modules and shuffle them through the global engine, one at a time ? Any suggestions would be appreciated. Regards Peter
  8. Good point, I'll see if I can find the package the Rest code resides in, thanks for the feedback.
  9. Hi I am using the Delphi Rest Client and OAuth libraries from the units REST.Utils, REST.Types, REST.Client, REST.Authenticator.OAuth, REST.Authenticator.OAuth.WebForm.Win I have two dll's that uses these units successfully and both have runtime packages turned on for xmlrtl;vcl;vclx;rtl However when I try to load both dll's in the same exe, I get the following exception. exception class : EFilerError exception message : A class named TOAuth1SignatureMethod_PLAINTEXT already exists. Because the rest code seems to be in the rtl package, and both dll's are loading rtl package at runtime, I thought it should be ok, but apparently not. This class TOAuth1SignatureMethod_PLAINTEX is in REST.Authenticator.OAuth unit in C:\Program Files (x86)\Embarcadero\Studio\19.0\source\data\rest At the bottom of this file is the cause initialization RegisterClasses([TOAuth1SignatureMethod_PLAINTEXT, TOAuth1SignatureMethod_HMAC_SHA1]); Does anyone have any ideas how to resolve this ? Regards Peter Bug report below running in 64 bit. Username : peter date/time : 2020-11-20, 10:59:23, 388ms computer name : PETER user name : peter registered owner : peter operating system : Windows 10 x64 build 19041 system language : English system up time : 3 days 21 hours program up time : 2 minutes 47 seconds processors : 12x Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz physical memory : 4135/16235 MB (free/total) free disk space : (C:) 242.90 GB display mode : 2560x1440, 32 bit process id : $5f54 allocated memory : 1.60 GB largest free block : 130989.73 GB executable : prog.exe exec. date/time : 2020-11-20 09:15 version : compiled with : Delphi 10.2 Tokyo madExcept version : 5.0.99 callstack crc : $398bae85, $14cecb7b, $317ff7bb exception number : 1 exception class : EFilerError exception message : A class named TOAuth1SignatureMethod_PLAINTEXT already exists. main thread ($6668): 033dcc0c +0cc rtl250.bpl 033de3fd +02d rtl250.bpl System Classes.RegisterClass 033de48e +01e rtl250.bpl System Classes.RegisterClasses 0328a309 +139 rtl250.bpl System _StartLib 7ffd4d02 +0df ntdll.dll LdrLoadDll 7ffd4ab8 +15b KERNELBASE.dll LoadLibraryExW 08502849 +049 MACM.dll unModuleInterface 164 +4 TModuleInterface.OpenLibrary 0880de40 +010 MACM.dll unRestInterface 213 +1 TRESTInt.OpenLibrary 08502673 +0a3 MACM.dll unModuleInterface 106 +9 TModuleInterface.Create 0880dd4b +08b MACM.dll unRestInterface 204 +1 TRESTInt.Create