Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You can pass it as an argument by just… passing it as an argument. Presumably you want to quote it rather than passing it as an arbitrary number of arguments that need to be escaped and so on, but that's easy with <a href="http://docs.python.org/3/library/shlex.html#shlex.quote" rel="nofollow"><code>shlex.quote</code></a>. For example:</p> <pre><code>with open('bigfile.txt', 'rb') as infile: biginput = infile.read(2048) os.system('cprogram {}'.format(shlex.quote(biginput))) </code></pre> <hr> <p>If you get an error about the argument or the command line being too long for the shell… then you can't do it. Python can't make the shell do things it can't do, and you refuse to go around the shell (I think because of a misunderstanding, but let's ignore that for the moment). So, you will need some other way to pass the data.</p> <p>But that doesn't mean you have to store it in a file. You can use the shell from <code>subprocess</code> just as easily as from <code>os.system</code>, which means you can pass it to your child process's stdin:</p> <pre><code>with subprocess.Popen('cprogram {}'.format(shlex.quote(biginput)), shell=True, stdin=subprocess.PIPE) as p: p.communicate(biginput) </code></pre> <p>Since you're using <code>shell=True</code>, and not replacing either <code>stdout</code> or <code>stderr</code>, it will get the exact same terminal that it would get with <code>os.system</code>. So, for example, if it's doing, say, <code>isatty(fileno(stdout))</code>, it will be true if your Python script is running in a tty, false otherwise.</p> <hr> <p>As a side note, storing it in a <code>tempfile.NamedTemporaryFile</code> may not cost nearly as much as you expect it to. In particular, the child process will likely be able to read the data you wrote right out of the in-memory disk cache instead of waiting for it to be flushed to disk (and it may <em>never</em> get flushed to disk).</p> <hr> <p>I suspect that the reason you thought you couldn't use <code>subprocess</code> is that you were using <code>check_output</code> when you wanted <code>check_call</code>.</p> <p>If you use <code>check_output</code> (or if you explicit pass <code>stdout=PIPE</code> to most other <code>subprocess</code> functions), the child process's stdout is the pipe that you're reading from, so it's obviously not a tty.</p> <p>This makes sense: either you want to capture the output, in which case the C program can't output to the tty, or you want to let the C program output to the tty, in which case you can't capture it.* So, just don't capture the output, and everything will be fine.</p> <hr> <p>If I'm right, this means you have no reason to use the shell in the first place, which makes everything a whole lot easier. Of course your data might still be larger than the maximum system argument size** or resource limits***, even without the shell. On most modern systems, you can count on at least 64KB, so definitely try it first:</p> <pre><code>subprocess.check_call(['cprogram', biginput]) </code></pre> <p>But if you get an <code>E2BIG</code> error:</p> <pre><code>with subprocess.Popen(['cprogram', biginput], stdin=subprocess.PIPE) as p: p.communicate(biginput) </code></pre> <hr> <p>* Unless, of course, you want to <em>fake</em> a tty for your child process, in which case you need to look at <a href="http://docs.python.org/3/library/os.html#os.forkpty" rel="nofollow"><code>os.forkpty</code></a> and related functions, or the <a href="http://docs.python.org/3/library/pty.html#module-pty" rel="nofollow"><code>pty</code></a> module.</p> <p>** On most *BSD and related systems, <code>sysctl kern.argmax</code> and/or <code>getconf ARG_MAX</code> will give you the system limit, or <code>sysconf(_SC_ARG_MAX)</code> from C. There may also be a constant <code>ARG_MAX</code> accessible through <code>&lt;limits.h&gt;</code>. On linux, things are a bit more complicated, because there are a number of different limits (most of which are very, very high) rather than just one single limit. Check your platform's manpage for <code>execve</code> for the details.</p> <p>*** On some platforms, including recent linux, <code>RLIMIT_STACK</code> affects the max arg size that you can pass. Again, see your platform's <code>execve</code> manpage.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COOk you've written a lot of good info. I noticed that if I use "os.system()" then if I <ctrl>-c out of the c program, the Python program continues. If I use "subprocess.check_call()" then if I <ctrl>-c out of the c program, the Python program terminates as well. I need the former behavior. I also need the (interactive) c program to get both its input and output from the user from the shell. You statement that I can pass 64K in on the command line interested me. So I put the entire json text into single quotes and passed it in on the command line. That worked.
      singulars
    2. CO@JoeC: It's a bad idea to just put it in single quotes, because JSON text can contain single quotes, and you aren't doing anything to escape them. That's exactly why quoting and escaping functions like `shlex.quote` exist—someone else has already worked through all the edge cases and made them work, so why repeat all their bugs?
      singulars
    3. CO@JoeC: As for `os.system` swallowing ctrl-c… it's generally considered a _good_ thing that `subprocess` gives you more control, not a bad thing. `check_call` will also raise an exception if the return value is 2, while `system` will just ignore it. You can choose to handle `CalledProcessError` or let it pass upward, and the same for `KeyboardInterrupt`. (And you can write wrapper functions to swallow or modify-and-rethrow or whatever any exceptions you want.)
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload