2

I'm trying to run this command through KennethReitz's Envoy package:

$ sqlite3 foo.db 'select * from sqlite_master' 

I've tried this:

r = envoy.run("sqlite3 foo.db 'select * from sqlite_master'")
sqlite3: Error: too many options: "*"

and this:

r = envoy.run(['sqlite3', 'foo.db', 'select * from sqlite_master'])
AttributeError: 'NoneType' object has no attribute 'returncode'

additional quoting & escaping doesn't seem to help. Any suggestions?

FYI: This is what I had to do for now:

cmd = "sqlite3 %(database)s 'select * from sqlite_master'" % locals()
os.system(cmd)

Note that this is a contrived example, and that most of the unix shell commands that I'd like to issue aren't just a simple select that could be easily done via SQLAlchemy.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Buford Sweatley
  • 327
  • 1
  • 3
  • 6
  • 2
    The sqlite3 module is included in python's standard libraries. http://docs.python.org/library/sqlite3.html You'd be able to access the data from the db more directly that way. – monkut Feb 02 '12 at 03:29
  • Thanks - I agree, and am mostly using sqlalchemy. But I also have to run quite a few shell commands that will require subprocess, os.system, popen, or envoy. I'm hoping to confirm that Envoy will work for these simple commands. – Buford Sweatley Feb 02 '12 at 03:56
  • you could write them as a single script and then spin them off with the multiprocessing module. – monkut Feb 02 '12 at 04:42
  • Yes, it would make it more difficult to generate the command. I'd love some flexibility. This isn't asking for much, and people frequently do exactly this with perl or python using popen, os.system(), etc. – Buford Sweatley Feb 02 '12 at 05:13

2 Answers2

2

This will not work in envoy because envoy splits the commands and pass them to subprocess. Even if you try with subprocess.Popen(command, shell = False) you will end up getting sqlite3 terminal. Both subprocess and envoy fails to address this, I will be happy if you can open an issue in envoy since I am contributing to it, I will be thinking about this.

Kracekumar
  • 19,457
  • 10
  • 47
  • 56
1

You could use subprocess:

from subprocess import check_output as qx

output = qx(['sqlite3', 'foo.db', 'select * from sqlite_master'])
print output

Or sqlite3 module:

import sqlite3

conn = sqlite3.connect('foo.db')
for row in conn.execute('select * from sqlite_master'):
    print row

If you still want to use envoy then you could fix it as:

import envoy

r = envoy.run([["sqlite3", "foo.db", "select * from sqlite_master"]])
print r.std_out
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 1
    Thanks - the list within a list for envoy did the trick. Can you tell me what's going on there? – Buford Sweatley Feb 02 '12 at 19:20
  • @Buford Sweatley: I've just looked at the [source](https://github.com/kennethreitz/envoy/blob/master/envoy/core.py#L158). The original problem (string argument) seems like a bug in `envoy`. – jfs Feb 02 '12 at 19:40
  • This might be a silly question but I tried to "r = envoy.run('rm /tmp/*')" and it didn't work. r.std_error said: "No such file or directory" This was the only more or less related thread. Is this actually related? – Jouke Waleson Jul 30 '12 at 12:33
  • @JoukeWaleson: `subprocess.check_call(['rm']+glob.glob('/tmp/*'))` or better: `for path in glob.iglob('/tmp/*'): os.remove(path)`. Note: both fail if `/tmp/` has subdirectories. I guess `envoy.run` doesn't invoke a shell by default so `rm` sees `/tmp/*` filename literally. You could [ask the question](http://stackoverflow.com/questions/ask), somebody might provide more details. – jfs Jul 30 '12 at 12:52
  • Thanks, just did: http://stackoverflow.com/questions/11722318/using-rm-wildcard-in-envoy-no-such-file-or-directory – Jouke Waleson Jul 30 '12 at 13:12