8
$\begingroup$

I would like to pass Mathematica variable values to Python. But I found that it was not that trivial. For example, a typical way would be:

session = StartExternalSession["Python"];
l = Range[10];
res = ExternalEvaluate[session, "
l=list(<*l*>)
print(l)
l
"];
DeleteObject[session];

The results are: a Python expression [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:

res
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

It seems to work. However, when I tried to define a Mathematica function with local variables:

f[l_] := Module[
  {session, res},
  session = StartExternalSession["Python"];
  res = ExternalEvaluate[session, "
l=list(<*l*>)
print(l)
l
"];
  DeleteObject[session];
  Return[res]
  ]

Clear[l]
f[Range[10]]

it didn't work. It looks like the "<* *>" notation doesn't accept local variables (in this case, l_List). I tried several patterns, but all my attempts failed in vain. After all, I needed to override the local variable l_LIst with another global variable l_List as follows.

l = Range[10];
f[Range[10]]

Did I miss something? Any suggestion would be welcome.

$\endgroup$

3 Answers 3

8
$\begingroup$

From the documentation (Scope > Command Otions > Arguments):

ExternalEvaluate[
 "Python",
 "lambda a, b: a+b" -> {1, 3}
 ]
(* 4 *)

So the easiest will be to define a function in your Python expression. Then you can pass the arguments as shown above, without any issues caused by localization and similar effects.

$\endgroup$
1
  • $\begingroup$ Lukas, Thank you for your comments. Since I wasn't familiar with the lambda function, it was very informative. My intention was to find a way to copy Mathematica complex expressions (e.g., association expressions) to Python variables and process them with Python; In my particular case, your answer didn't directly solve my problems. But still insightful. I'll reconsider my issue based on your comments. $\endgroup$ Commented May 1, 2023 at 6:11
4
$\begingroup$

You can wrap python code into a function and use ExternalFunction. Pass values as args, forward args conversion is automatic.

session = StartExternalSession["Python"] ;

f = ExternalFunction[session, "def function(x): return ''.join(x)"] ;
x = {"a", "b", "c"} ;
f[x]
(* abc *)

f = ExternalFunction[session, "def function(x): return x**2"] ;
x = N[Range[10]] ;
f[x]
(* {1.`,4.`,9.`,16.`,25.`,36.`,49.`,64.`,81.`,100.`} *)

f = ExternalFunction[session, "import numpy\ndef function(x): return numpy.asarray(x)**2"] ;
x = N[Range[10]] ;
f[x]
Normal[x]
(* NumericArray[...] *)
(* {1.`,2.`,3.`,4.`,5.`,6.`,7.`,8.`,9.`,10.`} *)

DeleteObject[session];
$\endgroup$
1
  • $\begingroup$ I.M., Thank you for your response. It is helpful. $\endgroup$ Commented May 1, 2023 at 6:12
2
$\begingroup$

From the help:

The command "cmd" may contain an inline template expression <expr>. This evaluates expr before "cmd" is sent to the external evaluator.

Now, the problem seems to com from this step. As long as the template contains local or global variables, this will work:

f[ll_] := Module[{session, res, arg},
  arg = ll;
  session = StartExternalSession["Python"];
  res = ExternalEvaluate[session, "
l=list(<*arg*>)
print(l)
"];
  DeleteObject[session];
  Return[res]]

f[Range[10]]

However, the template fill in does not work with function arguments:

f[ll_] := Module[{session, res, arg},
  session = StartExternalSession["Python"];
  res = ExternalEvaluate[session, "
l=list(<*ll*>)
print(l)
"];
  DeleteObject[session];
  Return[res]]

f[Range[10]]
$\endgroup$
3
  • $\begingroup$ Daniel, Thank you for your response. I don't know why, but your code doesn't work in my environment; the message I've got is: 'WLSymbol' object is not iterable" Any suggestions? $\endgroup$ Commented May 1, 2023 at 6:20
  • $\begingroup$ Replace l=list(<*arg*>)by l=list(<* Evaluate[arg] *>) $\endgroup$ Commented May 1, 2023 at 18:59
  • $\begingroup$ The problem seems that <*arg*> only takes global variables. Therefore do not make arg an local variable, but a global one. $\endgroup$ Commented May 4, 2023 at 9:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.