tags:

views:

323

answers:

3

This is a snip-it of python I am working on right now - I did not list all of this code, so I apologize if something you need is "missing" - I think I can explain it well enough without the rest of it...

Below there is a function main() - this is not explicitly defined in my script - it is imported from another script made by someone else. When it is called, it outputs a very long list of every single available module python has available to call. I am trying to add line numbers to each module. So when it outputs it's a very long list of module names (I assume the function main() is putting "\n" breaks after each module because it prints one module, then a new line, then another module name). What I am TRYING to do is take those values, and add a line number in front of each module name.

   elif x == "list" or x == "1":

            print "\n loading... please wait"
            time.sleep(2)
            counter=0

            lnumber = 0
            all_mods = (main())

            for x in all_mods: 
                print lnumber, x
                lnumber = lnumber + 1
                counter = counter + 1

            print "-" * 30, "\nTotal number of modules detected: ", counter

**I understand the lnumber and counter are reporting the same thing, however I did this on purpose because it is consistent with the code I have elsewhere in the document which did not use this setup.

When this snippet of code is ran (with the other parts of the script) it reports back:

Traceback (most recent call last):
  File "C:\Users\jc\Documents\Python Projects\Projects\myOwnfns\helpwiz.py", line 131, in <module>
    main_loop()
  File "C:\Users\jc\Documents\Python Projects\Projects\myOwnfns\helpwiz.py", line 90, in main_loop
    for x in all_mods: #this variable comes from "list_all_mods" - an external script taken from another author.
TypeError: 'NoneType' object is not iterable
+2  A: 

The function main prints the lines to standard output; it doesn't return anything. More precisely it returns the None object, so all_mods is None. That's the cause for "'NoneType' object is not iterable", because you're trying to iterate over it with for x in all_mods.

Here's a terribly hackish solution that will work:

import sys, StringIO
buffer = StringIO.StringIO()
sys.stdout = buffer
main()
buffer.seek(0)
all_mods = buffer.read().splitlines()
sys.stdout = sys.__stdout__
balpha
I figured as much (thank you for confirming), but is there a way to "tap into the standard output" and put line numbers in front of them?Ultimately, what I want to do is map the line numbers to the module names (like a dictionary of sorts) so rather than type the module name you type the line number and then can work with it like that...I was thinking of taking the output from main() and putting it into a dictionary-type container then printing it out... (it prints first now and does nothing with the dictionary) - how can I accomplish this?
Nascent_Notes
A: 

I'd recommend refactoring list_all_mods(), if at all possible. In particular, change it to return a list of values, rather than printing them; or turn it into a new function find_all_mods() that returns a list, and redefine list_all_mods():

def list_all_mods(): 
    print '\n'.join(find_all_mods())

I know it's not your code, so this might not be an option. If not, then balpha's hack is probably the best you can do. After that, to print modules with line numbers, you can do:

for (i, module_name) in enumerate(all_mods):
    # n.b.: we use i+1 because we want numbering to start from 1.
    print "%4d %s" % (i+1, module_name)

p.s., I'm not sure what counts as "all modules" to you, but if it's the modules that are currently imported, you can get this by just looking at sys.modules.keys().

Edward Loper
A: 

The nl command does this for you.

python the_existing_program.py | nl

Should do what you want.

If you're working in windows, then you can write a version of nl very easily.

import fileinput
for n, line in enumerate( fileinput.input() ):
    print "%d %s" % ( n, line )

Let's say you called that nl.py.

python the_existing_program.py | python nl.py

This will work and doesn't require modifications to the original program.

S.Lott
I found "http://www.ncsa.illinois.edu/UserInfo/Resources/Hardware/IBMp690/IBM/usr/share/man/info/en_US/a_doc_lib/cmds/aixcmds4/nl.htm" that references the "nl" command, I understand what it does, but I cannot get it to work at all - I tried executing from command prompt (win32), and IDLE, looked in help(), tried to load and search for any modules named nl - and I am not seeing it...
Nascent_Notes
@Nascent_Notes: Please update your question to say Win 32. There is no `nl` command in Windows.
S.Lott