2

This is a followup to this Stackoverflow post

How to use Python variables in Google Colab terminal command?

Which asks how to send python variables to the command line.

The answer is you need to place a $ in front of it. In other cases, you need to quote everything like this '$variable'

This works for me except for curl commands. For example

emailBody1 = ' this is some test text'

!curl -X POST 'http://localhost.yxy' -H "Content-Type: application/json" -d '{"emails": [{"emailBody": '$emailBody1'}}'

I tried no quotes, single quotes, and double quotes. No quotes results in an error, and single/double quotes just sends whatever is inside as a string; no reference to the variable.

SantoshGupta7
  • 5,607
  • 14
  • 58
  • 116
  • 1
    on https://curl.trillworks.com/ you can convert curl command to python code with module `requests` and later use only python for this. – furas Feb 25 '20 at 23:48
  • 1
    Oh -- yeah; in python as opposed to the Linux command line, there's no reason to use `jq`, *or* bash at all. Python has perfectly good network functionality. Use it. – Charles Duffy Feb 25 '20 at 23:54
  • "Immediate problem, though, is that emailBody1 = ' this is some test text' doesn't assign a variable emailBody at all. ". I am not trying to send a variable to "emailBody", which is the key. I am trying to assign a variable to the value, which is emailBody1 – SantoshGupta7 Feb 25 '20 at 23:54
  • Um. So you're expecting your *Python* variables to be accessible to a *shell* interpreter that that Python instance starts? That... doesn't work that way. – Charles Duffy Feb 25 '20 at 23:55
  • 1
    There is absolutely no reason to be doing this. Use a library like `requests` instead of shelling out to `curl`. – chepner Feb 25 '20 at 23:55
  • "Um. So you're expecting your Python variables to be accessible to a shell interpreter that that Python instance starts?" Yes, using '$variable' works for other terminal commands, but doesn't seem to work for curl commands for some reason. – SantoshGupta7 Feb 25 '20 at 23:56
  • I don't see how it would work for *any* command. `$variable` accesses *shell* variables, not *Python* variables, unless Jupyter is doing some kind of magic behind your back instead of executing exactly what you tell it to. – Charles Duffy Feb 25 '20 at 23:56
  • "I don't see how it would work for any command. $variable accesses shell variables, not Python variables." . I am not an expert in this, but it somehow definitely works in Google Colab. This post gives more details https://stackoverflow.com/questions/52851718/how-to-use-python-variables-in-google-colab-terminal-command . My issue is somehow it doesn't work for curl commands. – SantoshGupta7 Feb 25 '20 at 23:58
  • So, that smells like Colab is trying to parse your shell syntax and doing its own variable substitution. It's not surprising that it gets the details wrong. – Charles Duffy Feb 25 '20 at 23:59
  • it works for me only if I create full JSON with extra `' '` - `emailbody = '\'{"emails": [{"emailBody": "this is some test text" }]}\''` and later use `-d $emailbody`. I tested with http://httpbin.org/post which send it back in response. – furas Feb 26 '20 at 00:00
  • If it doesn't work for this curl command, btw, I'll bet it also won't work for `!printf '%s\n' 'Prefix'"$emailBody1"'Suffix'`. If that's true, you should be able to build a question that's more narrowly about Jupyter and not about curl specifically. – Charles Duffy Feb 26 '20 at 00:00
  • 1
    ...which is to say, whatever magic in Jupyter tries to perform substitutions in shell commands presumably just doesn't understand shell syntax well enough to actually do it right. Nothing specific to curl. – Charles Duffy Feb 26 '20 at 00:02

2 Answers2

3

If you really insist on using curl for this, use subprocess to run a copy explicitly so you don't depend on Jupyter trying to do magic.

import subprocess, json
emailBody1 = ' this is some test text'

subprocess.run([
  'curl',
  '-X', 'POST',
  '-H', 'Content-Type: application/json',
  '-d', json.dumps({"emails": [{"emailBody": emailBody1}]}),
  'http://localhost.yxy',
])

This also has the advantage of using Python's json.dumps() to generate your JSON text, which won't break down in a number of cases where the other approach would (f/e, if your email text contains newlines, literal double quotes, or other special characters).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
3

This works for me

-d  '{{"emails": [{{"emailBody": "$emailBody1" }}]}}'

or

-d  '{{"emails": [{{"emailBody": "{emailBody1}" }}]}}'

All string is inside ' ' (or " ") without spliting to 'string' $var 'string'

And normal { } has to be converted to {{ }} because it uses { } to put values from variables.


I tested it with http://httpbin.org/post which sends back all data so I could see what was send.

emailBody1 = ' this is some test text'

!curl -X POST 'http://httpbin.org/post' -H "Content-Type: application/json" -d  '{{"emails": [{{"emailBody": "{emailBody1}" }}]}}'
furas
  • 134,197
  • 12
  • 106
  • 148