Python: print doesn't work, script hangs endlessly

对着背影说爱祢 提交于 2020-01-16 05:26:16

问题


Using Python 2.6, I wrote a script in Windows XP.

The script does the following:

Input: Domain name (ie: amazon.com)

The script queries DNS via the dnspython module and returns any A record IP Addresses. The output is in a special format needed for a specific application which utilizes this data.

This works fine in Windows, but when I've placed this on my Linux server, I'm getting some unusual and inconsistent results.

When run for the first time, it completes as expected. If I run it again immediately, the script will just hang and do nothing, no output, and the script won't end either. If I use CTRL-C to exit the process, it prints! (almost as it had been buffered, but no written to the terminal)

I've tried various techniques to fix this issue, like forcing sys.stdout.flush() after print (though, print should automatically flush anyways) and have had no luck.

If I wait some time (a few minutes), and run the script again, it will work again (once) and then subsequent attempts will continue to fail. I'm not sure what is going on... has anyone else experienced anything like this?

Python 2.6 on both Windows and Linux (Ubuntu).

Here is my script:

from dns.resolver import Resolver
from dns.exception import DNSException
from cStringIO import StringIO
import sys

def maltego_transform(entities, messages = ''):    
    print '''<MaltegoMessage>
<MaltegoTransformResponseMessage>
<Entities>
{0}
</Entities>
<UIMessages>
{1}
</UIMessages>
</MaltegoTransformResponseMessage>
</MaltegoMessage>'''.format(entities, messages)

def domain_to_ip(domain):
    resolver = Resolver()
    results = []
    for type in ['A', 'AAAA']:
        try:
            query = resolver.query(domain, type)
        except DNSException:
            query = []
        results += query

    entities = StringIO()
    for answer in results:
        entities.write('''<Entity Type="IPAddress"><Value>{0}</Value></Entity>'''.format(answer))
    maltego_transform(entities.getvalue())

def domain_to_mxdomain(domain):
    resolver = Resolver()
    try:
        query = resolver.query(domain, 'MX')
    except DNSException:
        query = []

    entities = StringIO()
    for answer in query:
        entities.write('''<Entity Type="Domain"><Value>{0}</Value>
<AdditionalFields><Field Name="DomainType" DisplayName="Domain Type">Mail Exchange</Field></AdditionalFields>
</Entity>'''.format(answer.exchange))
    maltego_transform(entities.getvalue())

def main():
    options = {'domain_to_ip' : domain_to_ip,
               'domain_to_mxdomain' : domain_to_mxdomain}
    if len(sys.argv) > 2:
        func = options.get(sys.argv[1], None)
        if func:
            func(sys.argv[2])

if __name__ == '__main__':
    main()

Use: python myscript.py domain_to_ip amazon.com

2 parameters for this script, the first maps to the function to run, the second specifies the domain.


回答1:


Apparently dnspython wants 16 bytes of high-quality random numbers at startup. Getting them (from /dev/random) can block.

If you hit Ctrl+C, it actually catches the KeyboardInterupt exception and falls back on less-secure random numbers (taken from the current system time). Then your program finishes running.

The code in question is here: http://www.dnspython.com/docs/1.7.1/html/dns.entropy-pysrc.html

I guess I would consider this a bug in dnspython. It should find a way not to block there, and fall back on /dev/urandom. In any case it shouldn't silence a KeyboardInterrupt.




回答2:


Have you tried doing

entities = StringIO()
for answer in results:
    entities.write('''<Entity Type="IPAddress"><Value>{0}</Value></Entity>'''.format(answer))
entities.flush()
maltego_transform(entities.getvalue())
entities.close()


来源:https://stackoverflow.com/questions/1799462/python-print-doesnt-work-script-hangs-endlessly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!