Here are two issues you may want to be aware of. The discussion below is relevant for Windows and not so much for Unix variants.
Using Python Raw strings for directories
$onEmbeddedCode Python: dir = r"%system.fp%" $offEmbeddedCode |
--- Initialize embedded library embpycclib64.dll |
dir = r"%system.fp%\"
This will generate a path: C:\Users\erwin\Downloads\\. The double \\ is not a problem as Windows will interpret this the same as a single \.
Note: there is a reason why other languages use a more complicated raw string:
- R: r"(C:\Users\erwin\Downloads\)" or even more complex versions in case your string literal contains a )".
- C++: R"(C:\Users\erwin\Downloads\)". This again uses )" to terminate the string. We can make this more complicated to make it more difficult for the literal to contain the terminator.
GAMS System Directory
$call "echo #### GAMS: system
directory=[%gams.sysdir%]" $onEmbeddedCode Python: ws = GamsWorkspace() $offEmbeddedCode |
#### GAMS: system directory=[c:\gams\41\]#### Embedded Python: system directory=[C:\GAMS\42]
Obviously, this behavior is not what we want. GAMS itself uses a different GAMS version than the embedded Python code. This is likely a very dangerous situation: lots of possibilities of mismatched libraries. In this example, GAMS itself infers the system directory (sysdir) from how it was invoked, while the Python API uses the Windows registry settings. We can make things even worse. If we just use GAMS from a network drive without local installation, we may get:
Exception from Python (line 46): Could not find a GAMS installation, must manually specify system_directory
(It is a bit counter-intuitive that while GAMS is running, the Python API can't figure out the correct location of this GAMS system).
One way to make these problems go away is to use:
ws = GamsWorkspace(system_directory=r"%gams.sysdir%\")
Note again the extra \ (see the discussion in the previous section). Now, I see:
#### GAMS: system directory=[c:\gams\41\]
#### Embedded Python: system directory=[C:\GAMS\41]
The system directory is now the same. Except for a small inconsistency in the trailing backslash (I think they should preferably be 100% the same).
Besides GamsWorkspace, this may affect a few other functions and constructors. I saw these problems occurring when using c = gt.Container() from the gamstransfer package. Again the fix was to use: c = gt.Container(system_directory=r"%gams.sysdir%\").
Conclusion
A few issues cropped up when doing some work using embedded Python in GAMS:
- Trailing backslashes in directory names can be a problem when used in Python scripts.
- Some parts of the GAMS Python API have problems finding the correct system directory.
References
- Python 3 documentation, Lexical Analysis, String and Bytes literals, https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
It appears the embedded Python suggests to find %gams.sysdir% in the environment. Python fails to find it when it is not explicitly initialized, and thus continue to take value from the registry. If you can issue system command "set" without parameters (to list all environment variables) from GAMS and Python in initial and patched runs, then you could identify the variable which one Python replaces from the registry. In this case you can supplement the environment before GAMS invoke: thru the shortcut on desktop or start menu (in the shortcut parameters you can specify the batch and the starting folder), or invoke console and issue the supplement set command.
ReplyDelete%gams.sysdir% is not a Windows environment variable but rather like a macro in GAMS defined by $set. (You can set environment variable using $setenv).
Delete