Best way to capture output from an exec'ed (or such) script?

Discussion in 'Python' started by exscape@gmail.com, Aug 2, 2007.

  1. Guest

    Hey everyone,
    I'm writing a tiny web server, mostly to learn - security and such is
    a non-issue, but learning how to make things secure is of course nice
    too. To be clear - I will most likely not even use it myself.

    In any case. I've added some minor scripting support, so that you can
    write dynamic pages in Python. To do this, I use execfile(), and pass
    the script a dictionary with some basic variables. The script then
    sets a "ret" variable that's sent back to the browser. That's some
    major ugliness right there! If I do a "print" inside the script, then
    it'll end up on the server console. I want it to end up in the web
    browser.

    How would I accomplish this, i.e. redirect the standard output to
    somewhere else, such as a variable in the calling script? If it's not
    easy (as in, quite trivial) just say so. I've been thinking about
    popen(2,3,4) but that's almost as ugly, if not even worse, than the
    current "solution".

    Thanks in advance.
     
    , Aug 2, 2007
    #1
    1. Advertising

  2. En Thu, 02 Aug 2007 16:48:06 -0300, <> escribió:

    > In any case. I've added some minor scripting support, so that you can
    > write dynamic pages in Python. To do this, I use execfile(), and pass
    > the script a dictionary with some basic variables. The script then
    > sets a "ret" variable that's sent back to the browser. That's some
    > major ugliness right there! If I do a "print" inside the script, then
    > it'll end up on the server console. I want it to end up in the web
    > browser.


    If `print` were a function, this would be easy: just provide a replacement
    into the dictionary you pass to the script. But print is a statement, and
    this becomes a bit harder.

    If your web server only processes a single request at a time, you can
    replace sys.stdout (and perhaps sys.stderr) with a suitable object having
    a write() function: a true open file, or a StringIO instance, or even a
    custom object that collects "printed" lines into a list.

    If your web server is multithreaded (or you use some other way to process
    many simultaneous requests) you have to be more careful - remember that
    sys.stdout is global, you must find a way to distinguish between output
    from different processes all going into the same collector.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Aug 3, 2007
    #2
    1. Advertising

  3. In article <>,
    Gabriel Genellina <> wrote:
    >En Thu, 02 Aug 2007 16:48:06 -0300, <> escribió:
    >
    >> In any case. I've added some minor scripting support, so that you can
    >> write dynamic pages in Python. To do this, I use execfile(), and pass
    >> the script a dictionary with some basic variables. The script then
    >> sets a "ret" variable that's sent back to the browser. That's some
    >> major ugliness right there! If I do a "print" inside the script, then
    >> it'll end up on the server console. I want it to end up in the web
    >> browser.

    >
    >If `print` were a function, this would be easy: just provide a replacement
    >into the dictionary you pass to the script. But print is a statement, and
    >this becomes a bit harder.
    >
    >If your web server only processes a single request at a time, you can
    >replace sys.stdout (and perhaps sys.stderr) with a suitable object having
    >a write() function: a true open file, or a StringIO instance, or even a
    >custom object that collects "printed" lines into a list.
    >
    >If your web server is multithreaded (or you use some other way to process
    >many simultaneous requests) you have to be more careful - remember that
    >sys.stdout is global, you must find a way to distinguish between output
    > from different processes all going into the same collector.

    .
    .
    .
    While we're on the subject of Web servers so small
    as to be educational, I'll recommend <URL:
    http://www.ibm.com/developerworks/web/library/wa-ltwebserv/ >.
     
    Cameron Laird, Aug 3, 2007
    #3
  4. Guest

    On Aug 2, 7:32 pm, "Gabriel Genellina" <> wrote:
    > If your web server is multithreaded (or you use some other way to process
    > many simultaneous requests) you have to be more careful - remember that
    > sys.stdout is global, you must find a way to distinguish between output
    > from different processes all going into the same collector.
    >

    Any ideas on how to do this? Is it even possible?

    -Greg
     
    , Aug 3, 2007
    #4
  5. Guest

    On Aug 3, 11:14 am, "" <>
    wrote:
    > On Aug 2, 7:32 pm, "Gabriel Genellina" <> wrote:> If your web server is multithreaded (or you use some other way to process
    > > many simultaneous requests) you have to be more careful - remember that
    > > sys.stdout is global, you must find a way to distinguish between output
    > > from different processes all going into the same collector.

    >
    > Any ideas on how to do this? Is it even possible?
    >
    > -Greg


    I'm actually worried about this now. Does anyone know of any
    potential solutions? Anything to at least get me started?

    -Greg
     
    , Aug 4, 2007
    #5
  6. En Sat, 04 Aug 2007 18:52:16 -0300,
    <> escribió:

    >> On Aug 2, 7:32 pm, "Gabriel Genellina" <> wrote:>
    >> If your web server is multithreaded (or you use some other way to
    >> process
    >> > many simultaneous requests) you have to be more careful - remember

    >> that
    >> > sys.stdout is global, you must find a way to distinguish between

    >> output
    >> > from different processes all going into the same collector.

    >
    > I'm actually worried about this now. Does anyone know of any
    > potential solutions? Anything to at least get me started?


    You can use threading.currentThread() to distinguish between threads, and
    a Lock (or RLock) to ensure the output doesn't get mixed:

    def write(msg):
    t = time.strftime("%x %X", time.localtime())
    who = threading.currentThread().getName()
    line = "%s (%-15.15s) %s\n" % (t, who, msg)
    OutputDebugString("%s (%-15.15s) %s\n" % (t, who, msg))
    loglock.acquire()
    try:
    with logfile() as f:
    f.write(line)
    finally:
    loglock.release()

    --
    Gabriel Genellina
     
    Gabriel Genellina, Aug 5, 2007
    #6
  7. Guest

    On Aug 5, 5:50 am, "Gabriel Genellina" <> wrote:
    > En Sat, 04 Aug 2007 18:52:16 -0300,
    > <> escribió:
    >
    > >> On Aug 2, 7:32 pm, "Gabriel Genellina" <> wrote:>
    > >> If your web server is multithreaded (or you use some other way to
    > >> process
    > >> > many simultaneous requests) you have to be more careful - remember
    > >> that
    > >> > sys.stdout is global, you must find a way to distinguish between
    > >> output
    > >> > from different processes all going into the same collector.

    >
    > > I'm actually worried about this now. Does anyone know of any
    > > potential solutions? Anything to at least get me started?

    >
    > You can use threading.currentThread() to distinguish between threads, and
    > a Lock (or RLock) to ensure the output doesn't get mixed:
    >
    > def write(msg):
    > t = time.strftime("%x %X", time.localtime())
    > who = threading.currentThread().getName()
    > line = "%s (%-15.15s) %s\n" % (t, who, msg)
    > OutputDebugString("%s (%-15.15s) %s\n" % (t, who, msg))
    > loglock.acquire()
    > try:
    > with logfile() as f:
    > f.write(line)
    > finally:
    > loglock.release()
    >
    > --
    > Gabriel Genellina



    Thanks, Gabriel. I'm not actually making the threads myself though.
    Rather it's a simple single threaded script running under FastCGI.
    Would your method still work? I don't know too much about how FastCGI
    works. Perhaps that's where I should start.

    -Greg
     
    , Aug 5, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Darrel
    Replies:
    4
    Views:
    1,161
    Andy G
    Nov 1, 2004
  2. Peter A. Schott
    Replies:
    4
    Views:
    603
    Peter A. Schott
    Feb 7, 2006
  3. David T. Ashley
    Replies:
    22
    Views:
    1,002
    Malcolm McLean
    Jan 30, 2007
  4. Googy
    Replies:
    1
    Views:
    140
    Robert Klemme
    Jan 26, 2007
  5. Stan R.
    Replies:
    1
    Views:
    146
Loading...

Share This Page