FAQ
I have a function which is intended for use at the interactive interpreter,
but may sometimes be used non-interactively. I wish to change it's output
depending on the context of how it is being called.


If the function is being called as if it were a procedure or command, that
is the return result is just ignored, I want to return one thing. But if it
is being called where the return result goes somewhere, I want to return
something else. Most importantly, I don't want to pass a flag to the
function myself, I want the function to know its own context.


I don't mind if it is CPython only, or if it is a bit expensive.




E.g.


def func():
     do_stuff()
     if procedure: # FIXME what goes here???
         return "Awesome"
     else:
         return 999


Now I can do this:




x = func()
assert x == 999


L = [1, 2, func(), 4]
assert L[2] == 999


func()
# interactive interpreter prints "Awesome"


Is such a thing possible, and if so, how would I do it?


If I did this thing, would people follow me down the street booing and
jeering and throwing things at me?








--
Steven

Search Discussions

  • Sven R. Kunze at Sep 10, 2015 at 6:03 pm
    http://stackoverflow.com/questions/2356399/tell-if-python-is-in-interactive-mode



    On 10.09.2015 19:54, Steven D'Aprano wrote:
    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.

    If the function is being called as if it were a procedure or command, that
    is the return result is just ignored, I want to return one thing. But if it
    is being called where the return result goes somewhere, I want to return
    something else. Most importantly, I don't want to pass a flag to the
    function myself, I want the function to know its own context.

    I don't mind if it is CPython only, or if it is a bit expensive.


    E.g.

    def func():
    do_stuff()
    if procedure: # FIXME what goes here???
    return "Awesome"
    else:
    return 999

    Now I can do this:


    x = func()
    assert x == 999

    L = [1, 2, func(), 4]
    assert L[2] == 999

    func()
    # interactive interpreter prints "Awesome"

    Is such a thing possible, and if so, how would I do it?

    If I did this thing, would people follow me down the street booing and
    jeering and throwing things at me?

    Probably. ;)


    But it it solve a problem, why not.




    Best,
    Sven
  • Ben Finney at Sep 10, 2015 at 6:14 pm


    I'm pretty sure Steven knows full well the answer to that question,
    which is not anything like the one he asked. Would you care to read the
    question he did ask?


    --
      \ ?The optimist thinks this is the best of all possible worlds. |
       `\ The pessimist fears it is true.? ?J. Robert Oppenheimer |
    _o__) |
    Ben Finney
  • Sven R. Kunze at Sep 10, 2015 at 6:34 pm

    On 10.09.2015 20:14, Ben Finney wrote:
    "Sven R. Kunze" <srkunze@mail.de> writes:
    I'm pretty sure Steven knows full well the answer to that question,
    which is not anything like the one he asked. Would you care to read the
    question he did ask?
    You are right. I turned out to me harder that I first thought.


    My initial guess was like: use AST. But now I see, it would be hard to
    get the source code.


    So, what actually could work, would be faking the interactive
    interpreter wrapping it up and thus have control over the source code
    typed in.


    Best,
    Sven
  • Sven R. Kunze at Sep 10, 2015 at 6:45 pm

    On 10.09.2015 20:34, Sven R. Kunze wrote:
    You are right. I turned out to me harder that I first thought.

    My initial guess was like: use AST. But now I see, it would be hard to
    get the source code.

    So, what actually could work, would be faking the interactive
    interpreter wrapping it up and thus have control over the source code
    typed in.

    Ha, got it: sys.settrace

    def traceit(frame, event, arg):
    ... return traceit

    sys.settrace(traceit)
    a=1
    (<fra...@...0x7ff9016785c0>, 'call', None)
    (<fra...@...0x7ff9016785c0>, 'line', None)
    (<fra...@...0x7ff9016785c0>, 'return', (u'a=1\n', 4))
    (<fra...@...0x7ff90168a1f8>, 'call', None)
    (<fra...@...0x7ff90168a1f8>, 'line', None)
    (<fra...@...0x7ff90168a1f8>, 'return', None)




    There you got the source. The use an AST to find out whether the line
    fits your definition of 'interactive'.


    That should only be necessary when the top frame is interactive.




    Best,
    Sven
  • Sven R. Kunze at Sep 10, 2015 at 6:56 pm
    Oops, missing print:

    On 10.09.2015 20:45, Sven R. Kunze wrote:
    On 10.09.2015 20:34, Sven R. Kunze wrote:
    You are right. I turned out to me harder that I first thought.

    My initial guess was like: use AST. But now I see, it would be hard
    to get the source code.

    So, what actually could work, would be faking the interactive
    interpreter wrapping it up and thus have control over the source code
    typed in.
    Ha, got it: sys.settrace
    def traceit(frame, event, arg):
    ... print(frame, event, arg)
    ... return traceit
    sys.settrace(traceit)
    a=1
    (<fra...@...0x7ff9016785c0>, 'call', None)
    (<fra...@...0x7ff9016785c0>, 'line', None)
    (<fra...@...0x7ff9016785c0>, 'return', (u'a=1\n', 4))
    (<fra...@...0x7ff90168a1f8>, 'call', None)
    (<fra...@...0x7ff90168a1f8>, 'line', None)
    (<fra...@...0x7ff90168a1f8>, 'return', None)


    There you got the source. The use an AST to find out whether the line
    fits your definition of 'interactive'.

    That should only be necessary when the top frame is interactive.


    Best,
    Sven
  • Sven R. Kunze at Sep 10, 2015 at 6:21 pm
    I need to add: you need to look up the stack to see if you have been
    called by __main__ and if __main__.__file__ is missing.


    Implementation: I would write decorator for your func.


    Best,
    Sven


    PS: did I say it would probably be a bad idea? If not, it would probably
    be a bad idea.


    PPS: what is the reason for this special behavior?

    On 10.09.2015 20:03, Sven R. Kunze wrote:
    http://stackoverflow.com/questions/2356399/tell-if-python-is-in-interactive-mode


    On 10.09.2015 19:54, Steven D'Aprano wrote:
    I have a function which is intended for use at the interactive
    interpreter,
    but may sometimes be used non-interactively. I wish to change it's
    output
    depending on the context of how it is being called.

    If the function is being called as if it were a procedure or command,
    that
    is the return result is just ignored, I want to return one thing. But
    if it
    is being called where the return result goes somewhere, I want to return
    something else. Most importantly, I don't want to pass a flag to the
    function myself, I want the function to know its own context.

    I don't mind if it is CPython only, or if it is a bit expensive.


    E.g.

    def func():
    do_stuff()
    if procedure: # FIXME what goes here???
    return "Awesome"
    else:
    return 999

    Now I can do this:


    x = func()
    assert x == 999

    L = [1, 2, func(), 4]
    assert L[2] == 999

    func()
    # interactive interpreter prints "Awesome"

    Is such a thing possible, and if so, how would I do it?

    If I did this thing, would people follow me down the street booing and
    jeering and throwing things at me?
    Probably. ;)

    But it it solve a problem, why not.


    Best,
    Sven
  • Ben Finney at Sep 10, 2015 at 6:12 pm

    Steven D'Aprano <steve@pearwood.info> writes:


    I have a function which is intended for use at the interactive
    interpreter, but may sometimes be used non-interactively. I wish to
    change it's output depending on the context of how it is being called.
    [?]

    x = func()
    assert x == 999

    L = [1, 2, func(), 4]
    assert L[2] == 999

    func()
    # interactive interpreter prints "Awesome"

    Is such a thing possible, and if so, how would I do it?

    That makes my skin creep. In the name of all the tea I've sacrificed to
    Python over the years, I pray this isn't possible.

    If I did this thing, would people follow me down the street booing and
    jeering and throwing things at me?

    First thing in the morning I will purchase a head of cabbage and store
    it in a warm place to make it rot, on the off chance you find some
    obscure way to achieve your benighted goal, just so I can be first in
    line to throw it as you pass.


    If ever I have to worry that some arbitrary Python function, unbenownst
    to me, might have a branch that will make it behave differently
    depending on *whether I bind a reference to its return value*, then I'll
    know you are sent to us as an evil spirit to make all software suck.


    --
      \ ?Nothing exists except atoms and empty space; everything else |
       `\ is opinion.? ?Democritus |
    _o__) |
    Ben Finney
  • Sven R. Kunze at Sep 10, 2015 at 6:24 pm

    On 10.09.2015 20:12, Ben Finney wrote:
    First thing in the morning I will purchase a head of cabbage and store
    it in a warm place to make it rot, on the off chance you find some
    obscure way to achieve your benighted goal, just so I can be first in
    line to throw it as you pass.

    Well, go ahead. And make photos!
  • Chris Angelico at Sep 10, 2015 at 6:39 pm

    On Fri, Sep 11, 2015 at 3:54 AM, Steven D'Aprano wrote:
    If the function is being called as if it were a procedure or command, that
    is the return result is just ignored, I want to return one thing. But if it
    is being called where the return result goes somewhere, I want to return
    something else. Most importantly, I don't want to pass a flag to the
    function myself, I want the function to know its own context.

    The first thing that comes to mind is a repr hack. If you make your
    function return an int-like object with a different repr, it could
    look like it's returning "Awesome" interactively. The usefulness of
    that depends on what the two forms are you're trying to return,
    though.


    Advantage: Doesn't get Ben's cabbage. I think.


    Disadvantage: Looks weird if you try to debug stuff and get the repr
    staring back at you.


    ChrisA
  • Laura Creighton at Sep 10, 2015 at 6:40 pm
    In a message of Fri, 11 Sep 2015 03:54:14 +1000, "Steven D'Aprano" writes:

    def func():
    do_stuff()
    if procedure: # FIXME what goes here???
    return "Awesome"
    else:
    return 999

    Now I can do this:


    x = func()
    assert x == 999

    L = [1, 2, func(), 4]
    assert L[2] == 999

    func()
    # interactive interpreter prints "Awesome"

    Is such a thing possible, and if so, how would I do it?

    Why, why, why do you want such a horrid thing?
    I have an function that isn't always doing what I want.
    I make a reference to it, so I can print it from time to time,
    and do some other things to try to see why sometimes I am getting
    an unwanted result.


    I can no longer debug my problem.
    You are seriously proposing this?

    If I did this thing, would people follow me down the street booing and
    jeering and throwing things at me?

    I might start ahead of time, just for thinking of it ...


    There has got to be a better way to get what you want -- or perhaps
    for you to want something saner.


    Laura
  • Paul Rubin at Sep 10, 2015 at 7:19 pm

    Steven D'Aprano <steve@pearwood.info> writes:
    I want the function to know its own context.
    I don't mind if it is CPython only, or if it is a bit expensive.

    That sounds crazy but if it's really what you want, you can probably
    fake it by examining the control stack using the backtrace module. I
    remember doing some hack of raising and catching an exception in order
    to retrieve the backtrace, but there might be a cleaner way that I
    didn't bother researching since it was just for a quick debugging
    problem.
  • Grant Edwards at Sep 10, 2015 at 7:23 pm

    On 2015-09-10, Steven D'Aprano wrote:


    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.

    [...]


    Sounds like an excellent way to waste somebody's afternoon when they
    start to troubleshoot code that's using your function. Over and over
    and over we tell newbies who have questions about what something
    returns or how it works


         "Start up an interactive session, and try it!".


    If word gets out about functions like yours, we sort of end up looking
    like twits.

    If I did this thing, would people follow me down the street booing
    and jeering and throwing things at me?

    Only the people who use your function. :)


    --
    Grant Edwards grant.b.edwards Yow! FROZEN ENTREES may
                                       at be flung by members of
                                   gmail.com opposing SWANSON SECTS ...
  • Akira Li at Sep 10, 2015 at 8:15 pm

    Grant Edwards <invalid@invalid.invalid> writes:

    On 2015-09-10, Steven D'Aprano wrote:

    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.
    [...]

    Sounds like an excellent way to waste somebody's afternoon when they
    start to troubleshoot code that's using your function. Over and over
    and over we tell newbies who have questions about what something
    returns or how it works

    "Start up an interactive session, and try it!".

    If word gets out about functions like yours, we sort of end up looking
    like twits.
    If I did this thing, would people follow me down the street booing
    and jeering and throwing things at me?
    Only the people who use your function. :)

    There are cases when it might be justified to alter the behavior e.g.,
    *colorama* allows to strip ANSI codes (e.g., disable colored output) if
    stdout is not a tty or *win-unicode-console* make sys.stdout to use
    WriteConsoleW() to write Unicode to Windows console (interactive case).
  • Random832 at Sep 10, 2015 at 8:42 pm

    On Thu, Sep 10, 2015, at 16:15, Akira Li wrote:
    There are cases when it might be justified to alter the behavior e.g.,
    *colorama* allows to strip ANSI codes (e.g., disable colored output) if
    stdout is not a tty or *win-unicode-console* make sys.stdout to use
    WriteConsoleW() to write Unicode to Windows console (interactive case).

    These conditions have nothing to do with whether it is running in the
    interactive interpreter, since you can still be on the console (or a
    tty) without being in the interactive interpreter. What you are talking
    about is detecting file redirection.
  • Grant Edwards at Sep 10, 2015 at 8:27 pm

    On 2015-09-10, Akira Li wrote:
    Grant Edwards <invalid@invalid.invalid> writes:
    On 2015-09-10, Steven D'Aprano wrote:

    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.
    [...]

    Sounds like an excellent way to waste somebody's afternoon when they
    start to troubleshoot code that's using your function. Over and over
    and over we tell newbies who have questions about what something
    returns or how it works

    "Start up an interactive session, and try it!".

    If word gets out about functions like yours, we sort of end up looking
    like twits.
    If I did this thing, would people follow me down the street booing
    and jeering and throwing things at me?
    Only the people who use your function. :)
    There are cases when it might be justified to alter the behavior e.g.,
    *colorama* allows to strip ANSI codes (e.g., disable colored output) if
    stdout is not a tty or *win-unicode-console* make sys.stdout to use
    WriteConsoleW() to write Unicode to Windows console (interactive case).

    I hate that sort of behavior also, but there's a long historical
    precident on Unix of command line utilities changing output format
    based on the results of isatty(STDIN_FILENO). IMO, that was
    definitely a mistake, and to this day regularly wastes my time when
    troubleshooting bash programs. But, it's been that way for 45 years,
    and it's not going to get fixed now. That sort of auto-magical
    "trying to guess what the user wants" instead of doing what the user
    says is what makes PHP smell so bad.


    A bad idea copied by thousand of people over several decades is still
    a bad idea.


    Let's not duplicate that mistake in Python.


    But, just to clarify, we're talking about the function's return value,
    not what it writes to stdout, right?


    --
    Grant Edwards grant.b.edwards Yow! I would like to
                                       at urinate in an OVULAR,
                                   gmail.com porcelain pool --
  • Rustom Mody at Sep 11, 2015 at 3:55 pm

    On Friday, September 11, 2015 at 12:53:28 AM UTC+5:30, Grant Edwards wrote:
    On 2015-09-10, Steven D'Aprano wrote:

    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.
    [...]

    Sounds like an excellent way to waste somebody's afternoon when they
    start to troubleshoot code that's using your function. Over and over
    and over we tell newbies who have questions about what something
    returns or how it works

    "Start up an interactive session, and try it!".

    If word gets out about functions like yours, we sort of end up looking
    like twits.
    If I did this thing, would people follow me down the street booing
    and jeering and throwing things at me?
    Only the people who use your function. :)



    In emacs:
    You can make a function a 'command' by putting an (interactive) into it.
    And then in the function if you check interactive-p (nowadays more fashionably
    'called-interactively-p' ) then it can figure out whether it was called from
    elisp or from emacs (top level)... and then change behavior accordingly.


    IOW this behavior is quite routine in emacs-land
    The norm being
    - Some functions are meant to be called only from Lisp
    - Some functions (commands) only from emacs
    - And then there are the 'Steven-functions'


    I find it curious that the people getting upset about this are all the
    emacs users [as far as I know] ;-)
  • Rustom Mody at Sep 11, 2015 at 3:55 pm

    On Friday, September 11, 2015 at 12:53:28 AM UTC+5:30, Grant Edwards wrote:
    On 2015-09-10, Steven D'Aprano wrote:

    I have a function which is intended for use at the interactive interpreter,
    but may sometimes be used non-interactively. I wish to change it's output
    depending on the context of how it is being called.
    [...]

    Sounds like an excellent way to waste somebody's afternoon when they
    start to troubleshoot code that's using your function. Over and over
    and over we tell newbies who have questions about what something
    returns or how it works

    "Start up an interactive session, and try it!".

    If word gets out about functions like yours, we sort of end up looking
    like twits.
    If I did this thing, would people follow me down the street booing
    and jeering and throwing things at me?
    Only the people who use your function. :)



    In emacs:
    You can make a function a 'command' by putting an (interactive) into it.
    And then in the function if you check interactive-p (nowadays more fashionably
    'called-interactively-p' ) then it can figure out whether it was called from
    elisp or from emacs (top level)... and then change behavior accordingly.


    IOW this behavior is quite routine in emacs-land
    The norm being
    - Some functions are meant to be called only from Lisp
    - Some functions (commands) only from emacs
    - And then there are the 'Steven-functions'


    I find it curious that the people getting upset about this are all the
    emacs users [as far as I know] ;-)
  • Denis McMahon at Sep 11, 2015 at 12:41 am

    On Fri, 11 Sep 2015 03:54:14 +1000, Steven D'Aprano wrote:


    If I did this thing, would people follow me down the street booing and
    jeering and throwing things at me?

    Yes

    x = func()
    x
    func()
    print x == func()
    assert x == func()

    Would you expect the last two calls to func() to return 999 or "Awesome"?
    Why? What is the material difference if any between interpreter (a)
    displaying the return value and (b) comparing the return value with
    another value.


    Debugging nightmare!


    --
    Denis McMahon, denismfmcmahon at gmail.com

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedSep 10, '15 at 5:54p
activeSep 11, '15 at 3:55p
posts19
users11
websitepython.org

People

Translate

site design / logo © 2019 Grokbase