2

I am trying to pass an argument to a bash script I am running in Python using subprocess.run(). It is for a loop that runs the command passing in arguments from a list. I am using the Twint library but that part isn't important; I am pointing it out to make the question easier to answer. Currently, this is what I have

search_item = "bitcoin"
cmd = 'twint -s "%s" --limit 2000 --near "New York" -o file2.csv --csv' % (search_item)
p1 = subprocess.run( cmd , shell = True) % (search_item)

However on trying to run it, I get the error:

TypeError: unsupported operand type(s) for %: 'CompletedProcess' and 'str'

Any help on how I can pass the arguments? Thank you in advance

Barmar
  • 741,623
  • 53
  • 500
  • 612
small potato
  • 29
  • 1
  • 4

1 Answers1

1

You don't need % (search_item) on the subprocess.run() line. You already substituted it when creating cmd on the previous line.

But there's nothing in your command that requires using shell=True, so you should put all the arguments in a list rather than a string. This is more efficient and avoids potential problems if strings contain special characters that require escaping.

search_item = 'bitcoin'
cmd = ['twint', '-s', search_item, '--limit', '2000', '--near', 'New York', '-o', 'file2.csv', '--csv']
subprocess.run(cmd)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • If you are not completely sure that the variable you want to interpolate is already a string, maybe use `str(search_item)` – tripleee Mar 02 '21 at 10:29
  • Thank you! I hadn't considered that. I am new to Python and your help has been invaluable. – small potato Mar 03 '21 at 06:26
  • 2
    GOTCHA ALERT! I want to point out that placing the command and its arguments in a list (sequence) does NOT work if you also use shell=True. In that case, only the first argument in the list (ie: that program or command you want to run) will be processed, and the remaining arguments are not passed to your requested command. Apparently, those additional arguments become arguments to the invoked shell instead, and thus don't make it to your command. This does not seem a sensible design, but that's what we have. – gwideman Feb 15 '22 at 09:26
  • 1
    @gwideman I always wondered why it worked at all to use a list with `shell=True`. I think those extra arguments will be available in your command if it uses positional arguments `$1`, `$2`, etc. Similar to executing `bash -c "command" args...` – Barmar Feb 15 '22 at 15:41