correct way to detect container type

Discussion in 'Python' started by Robin Becker, Oct 7, 2004.

  1. Robin Becker

    Robin Becker Guest

    I seem often to allow list/tuple arguments to be a singleton. This leads to code
    of the form

    if type(arg) not in (type(()),type([])): arg = [arg]


    or alternatively

    from type import ListType, TupleType
    _seqTypes = ListType, TupleType
    .......
    if type(arg) not in _seqTypes: ....

    is there a 'best' way to do this?
    --
    Robin Becker
     
    Robin Becker, Oct 7, 2004
    #1
    1. Advertising

  2. Robin Becker

    Peter Otten Guest

    Robin Becker wrote:

    > I seem often to allow list/tuple arguments to be a singleton. This leads
    > to code of the form
    >
    > if type(arg) not in (type(()),type([])): arg = [arg]
    >
    >
    > or alternatively
    >
    > from type import ListType, TupleType
    > _seqTypes = ListType, TupleType
    > ......
    > if type(arg) not in _seqTypes: ....
    >
    > is there a 'best' way to do this?


    I prefer

    isinstance(var, (list, tuple))

    to the above, but I don't think there is one correct way. Often you don't
    want a full-blown container, just an iterable. Then

    try:
    it = iter(var)
    except TypeError:
    it = iter([var])

    may be more appropriate. However, you will end up iterating over the
    characters if var is a string, which often has to be guarded against with
    an additional isinstance(basestring) test

    try:
    iter(var)
    except TypeError:
    var = [var]
    else:
    if isinstance(var, basestring): var = [var]

    Peter
     
    Peter Otten, Oct 7, 2004
    #2
    1. Advertising

  3. On Thu, 07 Oct 2004 10:30:22 +0100, Robin Becker <> wrote:
    > I seem often to allow list/tuple arguments to be a singleton. This leads to code
    > of the form
    >
    > if type(arg) not in (type(()),type([])): arg = [arg]
    >
    > or alternatively
    >
    > from type import ListType, TupleType
    > _seqTypes = ListType, TupleType
    > ......
    > if type(arg) not in _seqTypes: ....
    >
    > is there a 'best' way to do this?


    Depending upon the way you're using your sequence types, why don't you
    check for __getitem__? As far as I'm aware, it's all that is needed to
    support for loops. In some cases __len__ may also be needed. The
    advantage is that you will accept any user defined type that supports
    the sequence interface.


    --
    Carlos Ribeiro
    Consultoria em Projetos
    blog: http://rascunhosrotos.blogspot.com
    blog: http://pythonnotes.blogspot.com
    mail:
    mail:
     
    Carlos Ribeiro, Oct 7, 2004
    #3
  4. Carlos Ribeiro wrote:

    >On Thu, 07 Oct 2004 10:30:22 +0100, Robin Becker <> wrote:
    >
    >
    >>I seem often to allow list/tuple arguments to be a singleton. This leads to code
    >>of the form
    >>
    >>if type(arg) not in (type(()),type([])): arg = [arg]
    >>
    >>or alternatively
    >>
    >>from type import ListType, TupleType
    >>_seqTypes = ListType, TupleType
    >>......
    >>if type(arg) not in _seqTypes: ....
    >>
    >>is there a 'best' way to do this?
    >>
    >>

    >
    >Depending upon the way you're using your sequence types, why don't you
    >check for __getitem__? As far as I'm aware, it's all that is needed to
    >support for loops. In some cases __len__ may also be needed. The
    >advantage is that you will accept any user defined type that supports
    >the sequence interface.
    >
    >
    >
    >

    Careful! If all you are doing is:

    for x in arg:
    do something with x

    Then arg only needs to support __iter__ and need not be a sequence type
    nor support __getitem__.

    Aaron
     
    Aaron Bingham, Oct 7, 2004
    #4
  5. Robin Becker

    Tim Williams Guest

    smtplib, capturing output from set_debuglevel ??

    Can anyone suggest a way of capturing the output from smtplib's
    set_debuglevel into a list or dictionary (or anything else I can work
    with), Preferably not to a file, though if this is the only way, then it
    would be a start

    I have googled.

    TIA
     
    Tim Williams, Oct 7, 2004
    #5
  6. Robin Becker

    Robin Becker Guest

    Peter Otten wrote:

    > I prefer
    >
    > isinstance(var, (list, tuple))
    >
    > to the above, but I don't think there is one correct way. Often you don't
    > want a full-blown container, just an iterable. Then
    >
    > try:
    > it = iter(var)
    > except TypeError:
    > it = iter([var])
    >
    > may be more appropriate. However, you will end up iterating over the
    > characters if var is a string, which often has to be guarded against with
    > an additional isinstance(basestring) test
    >
    > try:
    > iter(var)
    > except TypeError:
    > var = [var]
    > else:
    > if isinstance(var, basestring): var = [var]
    >
    > Peter
    >

    lots of good ideas, but I think this breaks in 2.1 which we're still supporting.
    As do some of the iteration ideas.
    --
    Robin Becker
     
    Robin Becker, Oct 7, 2004
    #6
  7. Robin Becker

    Tim Williams Guest

    re: generating emails from Python

    >Is it possible, using email.MIMEMessage, to generate an email
    >with both HTML and plain text content, in such a way that:


    >1) it is displayed as HTML if the email client recognizes HTML;
    >2) it is displayed as plain text if the email client is HTML impaired?


    It should be, though I haven't tried it.

    This page might help you work out what you need to do.
    http://www.wilsonweb.com/wmt5/html-email-multi.htm

    HTH
     
    Tim Williams, Oct 7, 2004
    #7
  8. Robin Becker

    Peter Otten Guest

    Robin Becker wrote:

    > lots of good ideas, but I think this breaks in 2.1


    Yes, I think it requires at least 2.2. Back to square one then...

    Peter
     
    Peter Otten, Oct 7, 2004
    #8
  9. On Thu, 07 Oct 2004 11:16:47 +0100, Robin Becker <> wrote:
    > Peter Otten wrote:
    >
    > > I prefer
    > >
    > > isinstance(var, (list, tuple))
    > >
    > > to the above, but I don't think there is one correct way. Often you don't
    > > want a full-blown container, just an iterable. Then
    > >
    > > try:
    > > it = iter(var)
    > > except TypeError:
    > > it = iter([var])
    > >
    > > may be more appropriate. However, you will end up iterating over the
    > > characters if var is a string, which often has to be guarded against with
    > > an additional isinstance(basestring) test
    > >
    > > try:
    > > iter(var)
    > > except TypeError:
    > > var = [var]
    > > else:
    > > if isinstance(var, basestring): var = [var]
    > >
    > > Peter
    > >

    > lots of good ideas, but I think this breaks in 2.1 which we're still supporting.
    > As do some of the iteration ideas.
    > --
    > Robin Becker


    In 2.1 you can probably use the __getitem__ test.

    And I also think that you can define a conditional function in your
    library, as to make possible for 2.2+ users to pass iterators. It's a
    general solution, and more modern one at that.

    I'm now using generators for related things -- namely, when generating
    long output, I'm yielding individual strings for each line (or record)
    instead of concatenating them into a huge string. Depending on the
    system, it will make it more responsive. The performance impact is
    negligible; in some scenarios, it's in fact faster, because you can
    avoid lots of small string concatenations.

    --
    Carlos Ribeiro
    Consultoria em Projetos
    blog: http://rascunhosrotos.blogspot.com
    blog: http://pythonnotes.blogspot.com
    mail:
    mail:
     
    Carlos Ribeiro, Oct 7, 2004
    #9
  10. Robin Becker

    Steve Holden Guest

    Re: smtplib, capturing output from set_debuglevel ??

    Tim Williams wrote:

    > Can anyone suggest a way of capturing the output from smtplib's
    > set_debuglevel into a list or dictionary (or anything else I can work
    > with), Preferably not to a file, though if this is the only way, then it
    > would be a start
    >
    > I have googled.
    >


    All smtplib debug output is produced using print statements to standard
    ouput, so you could try creating a "file-like" object (such as a
    cStringIO) and temporarily replacing sys.stdout with it (saving
    sys.sdout and replacing it if other parts of your program need to use it).

    If you need help to work out the details, post again.

    regards
    Steeve
    --
    http://www.holdenweb.com
    http://pydish.holdenweb.com
    Holden Web LLC +1 800 494 3119
     
    Steve Holden, Oct 7, 2004
    #10
  11. Robin Becker

    Andrew Dalke Guest

    Re: smtplib, capturing output from set_debuglevel ??

    Tim Williams wrote:
    > Can anyone suggest a way of capturing the output from smtplib's
    > set_debuglevel into a list or dictionary (or anything else I can work
    > with),


    Looking at smtplib.py, all of the debug messages go to
    the module variable 'stderr', which is a reference to sys.stderr.

    That means you can replace smtplib.stderr with something
    of your own. Try this untested bit of code

    import cStringIO
    old_error = smtplib.error
    new_error = cStringIO.StringIO()
    try:
    smtplib.error = new_error
    ... do your smtplib call here ...
    finally:
    smtplib.error = old_error
    print "Debug messages"
    print new_error.getvalue()

    What this does is replace smtplib.error with a StringIO,
    which is a file-like object that stays in memory. I used
    the try/finally to ensure that the original error output
    file is restored after the smtplib call ends.

    There are other things you could do by making your own
    sufficiently file-like object instead of using StringIO.
    All it needs to do is implement the 'write' method.
    But it may have to accumulate several writes before it
    gets a full line.

    class ShowWrites:
    def write(self, text):
    print "Got", repr(text)

    To test it out, change my first example so it uses
    ShowWrite instead of StringIO and get rid of the
    last two lines

    new_error = ShowWrite()

    and get rid of these two lines

    old_error = smtplib.error
    new_error = ShowWrites()
    try:
    smtplib.error = new_error
    ... do your smtplib call here ...
    finally:
    smtplib.error = old_error



    Andrew
     
    Andrew Dalke, Oct 7, 2004
    #11
  12. Robin Becker

    Tim Williams Guest

    Re: smtplib, capturing output from set_debuglevel ??

    ----- Original Message -----
    From: "Steve Holden" <>


    > Tim Williams wrote:
    >
    > > Can anyone suggest a way of capturing the output from smtplib's
    > > set_debuglevel


    > All smtplib debug output is produced using print statements to standard
    > ouput, so you could try creating a "file-like" object (such as a
    > cStringIO) and temporarily replacing sys.stdout with it (saving
    > sys.sdout and replacing it if other parts of your program need to use it).
    >
    > If you need help to work out the details, post again.


    Many thanks Steve

    I have implemented your suggestion , but what is the best way to get the
    data out of the file-like object, the only option that seems to work for
    me is

    f.getvalue()

    which returns a string, but getvalue() doesn't "feel" right somehow. Am I
    missing something ?

    TIA
     
    Tim Williams, Oct 7, 2004
    #12
  13. Robin Becker

    Steve Holden Guest

    Re: smtplib, capturing output from set_debuglevel ??

    Tim Williams wrote:

    > ----- Original Message -----
    > From: "Steve Holden" <>
    >
    >
    >>Tim Williams wrote:
    >>
    >>
    >>>Can anyone suggest a way of capturing the output from smtplib's
    >>>set_debuglevel

    >
    >
    >>All smtplib debug output is produced using print statements to standard
    >>ouput, so you could try creating a "file-like" object (such as a
    >>cStringIO) and temporarily replacing sys.stdout with it (saving
    >>sys.sdout and replacing it if other parts of your program need to use it).
    >>
    >>If you need help to work out the details, post again.

    >
    >
    > Many thanks Steve
    >
    > I have implemented your suggestion , but what is the best way to get the
    > data out of the file-like object, the only option that seems to work for
    > me is
    >
    > f.getvalue()
    >
    > which returns a string, but getvalue() doesn't "feel" right somehow. Am I
    > missing something ?
    >

    If you want to use file primitives to read the value back, just create
    another one:

    inpt = StringIO.StringIO(firstStringIO.getvalue())

    then you can read the printed output from inpt just like a file.

    regards
    Steve
    --
    http://www.holdenweb.com
    http://pydish.holdenweb.com
    Holden Web LLC +1 800 494 3119
     
    Steve Holden, Oct 8, 2004
    #13
  14. Re: smtplib, capturing output from set_debuglevel ??


    > If you want to use file primitives to read the value back, just create
    > another one:
    >
    > inpt = StringIO.StringIO(firstStringIO.getvalue())
    >
    > then you can read the printed output from inpt just like a file.


    Or even:

    firstStringIO.seek(0)

    - Josiah
     
    Josiah Carlson, Oct 8, 2004
    #14
  15. Robin Becker

    Tim Williams Guest

    Re: smtplib, capturing output from set_debuglevel ??

    ----- Original Message -----
    From: "Josiah Carlson" <>


    >
    > > If you want to use file primitives to read the value back, just create
    > > another one:
    > >
    > > inpt = StringIO.StringIO(firstStringIO.getvalue())
    > >
    > > then you can read the printed output from inpt just like a file.

    >
    > Or even:
    >
    > firstStringIO.seek(0)
    >
    > - Josiah


    Steve, Andrew, Josiah,

    Thanks for your answers.

    The outgoing SMTP is multi-threaded, so the threads disrupt each other's
    output to the file-like object if there is any concurrent outgoing mail
    activity.

    Is there anyway I can seperate the output from each thread and capture it ?

    The outgoing threads are started with
     
    Tim Williams, Oct 8, 2004
    #15
  16. Robin Becker

    Steve Holden Guest

    Re: smtplib, capturing output from set_debuglevel ??

    Josiah Carlson wrote:

    >>If you want to use file primitives to read the value back, just create
    >>another one:
    >>
    >>inpt = StringIO.StringIO(firstStringIO.getvalue())
    >>
    >>then you can read the printed output from inpt just like a file.

    >
    >
    > Or even:
    >
    > firstStringIO.seek(0)
    >

    Yup, actually rather better than my hurried attempt.

    regards
    Steve
    --
    http://www.holdenweb.com
    http://pydish.holdenweb.com
    Holden Web LLC +1 800 494 3119
     
    Steve Holden, Oct 8, 2004
    #16
  17. Re: smtplib, capturing output from set_debuglevel ??

    Tim Williams wrote:
    > I have implemented your suggestion , but what is the best way to get the
    > data out of the file-like object, the only option that seems to work for
    > me is
    >
    > f.getvalue()
    >
    > which returns a string, but getvalue() doesn't "feel" right somehow. Am I
    > missing something ?


    I've never felt the name "spoke to me" very well either :), but
    it is the correct way to do it.

    Note also, regarding Steve's suggestion, that for simplicity
    in a small program you don't need to save sys.stdout if you
    are doing that just to restore it later, because sys.__stdout__
    is always the original value and a quick sys.stdout == sys.__stdout__
    will do the trick.

    -Peter
     
    Peter L Hansen, Oct 8, 2004
    #17
    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. Vivi Orunitia
    Replies:
    11
    Views:
    4,545
    Martijn Lievaart
    Feb 4, 2004
  2. Maitre Bart
    Replies:
    2
    Views:
    551
    Maitre Bart
    Feb 11, 2004
  3. Replies:
    5
    Views:
    336
  4. Steven D'Aprano

    Re: fastest way to detect a user type

    Steven D'Aprano, Feb 1, 2009, in forum: Python
    Replies:
    3
    Views:
    286
    Steven D'Aprano
    Feb 1, 2009
  5. Urs Thuermann
    Replies:
    6
    Views:
    518
    Urs Thuermann
    Nov 4, 2011
Loading...

Share This Page