Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python脚本在套接字连接期间无限冻结_Python_Django_Sockets - Fatal编程技术网

Python脚本在套接字连接期间无限冻结

Python脚本在套接字连接期间无限冻结,python,django,sockets,Python,Django,Sockets,我有一个简单的python脚本,可以更新数据库中justin.tv流的状态。这是一个基于Django的web应用程序。该脚本在我将其移动到生产服务器之前运行良好,但现在它出现超时或冻结问题。我通过添加try/except块并使脚本重试解决了超时问题,但我仍然无法解决冻结问题 我知道它冻结在行streamOnline=manager.getStreamOnline(stream.name,LOG)上。这与发生socket.timeout异常的位置相同。然而,有时,它只是永远锁定。我无法想象pyth

我有一个简单的python脚本,可以更新数据库中justin.tv流的状态。这是一个基于Django的web应用程序。该脚本在我将其移动到生产服务器之前运行良好,但现在它出现超时或冻结问题。我通过添加try/except块并使脚本重试解决了超时问题,但我仍然无法解决冻结问题

我知道它冻结在行
streamOnline=manager.getStreamOnline(stream.name,LOG)
上。这与发生
socket.timeout
异常的位置相同。然而,有时,它只是永远锁定。我无法想象python会无限冻结的场景。下面是冻结脚本的代码。我正在链接下面的website.networkmanagers,以及我正在使用的oauth和justin.tv python库

import sys, os, socket

LOG = False

def updateStreamInfo():
    # Set necessary paths
    honstreams = os.path.realpath(os.path.dirname(__file__) + "../../../")
    sys.path.append(honstreams)
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

    # Import necessary moduels
    from website.models import Stream, StreamInfo
    from website.networkmanagers import get_manager, \
                                        NetworkManagerReturnedErrorException

    # Get all streams
    streams = Stream.objects.all()

    try:
        # Loop through them
        for stream in streams:

            skipstream = False

            print 'Checking %s...' % stream.name,
            # Get the appropriate network manager and
            manager = get_manager(stream.network.name)

            # Try to get stream status up to 3 times
            for i in xrange(3):
                try:
                    streamOnline = manager.getStreamOnline(stream.name, LOG)
                    break
                except socket.error as e:
                    code, message = e

                    # Retry up to 3 times
                    print 'Error: %s. Retrying...'

            # If this stream should be skipped
            if(skipstream):
                print 'Can\'t connect! Skipping %s' % stream.name
                continue

            # Skip if status has not changed
            if streamOnline == stream.online:
                print 'Skipping %s because the status has not changed' % \
                      stream.name
                continue

            # Save status
            stream.online = streamOnline
            stream.save()

            print 'Set %s to %s' % (stream.name, streamOnline)

    except NetworkManagerReturnedErrorException as e:
        print 'Stopped the status update loop:', e

if(__name__ == "__main__"):
    if(len(sys.argv) > 1 and sys.argv[1] == "log"):
        LOG = True

    if(LOG): print "Logging enabled"

    updateStreamInfo()



脚本冻结示例

foo@bar:/…/honstreams/honstreams#python网站/scripts/updateStreamStatus.py
检查愤怒测试。。。跳过angrytestie,因为状态未更改
正在检查chustream。。。正在跳过chustream,因为状态未更改
检查香菜。。。跳过芫荽叶,因为状态未更改

|在JtvClient.py中,它使用httplib处理连接。您是否尝试过将此更改为使用httplib2

除了暗中刺探之外,我会在代码中添加很多日志语句,以便跟踪实际发生的事情以及它被卡住的地方。然后,我会确保它被卡住的地方可以在套接字上超时(这通常涉及到修补或分叉代码库),这样东西就会失败,而不是挂起

你说:

我知道它冻结在streamOnline=manager.getStreamOnline(stream.name,LOG)行上。这与socket.timeout异常发生的位置相同

错。它不会冻结在这一行,因为这一行是一个函数调用,它通过几个级别的其他模块调用许多其他函数。所以你还不知道程序冻结在哪里。此外,该行不是套接字超时发生的点。套接字超时只会发生在低级套接字操作(如select或recv)上,该操作在getStreamOnline触发的活动链中被多次调用

您需要在调试器中跟踪代码或添加打印语句,以准确跟踪挂起发生的位置。它可能是Python中的无限循环,但更可能是对操作系统网络功能的低级调用。在找到错误的来源之前,您无法执行任何操作


另外,键盘中断是一个合理的线索,表明问题出在JtvClient.py的第90行附近,所以输入一些打印语句,看看会发生什么。可能有一个愚蠢的循环一直在调用getresponse,或者你可能用错误的参数调用它,或者网络服务器真的坏了。缩小范围以减少可能性。

您是否尝试使用其他应用程序打开该连接?考虑到这是生产中的一个问题,也许您没有防火墙问题。

事实证明,在jtvClient.py中,此HTTP连接没有超时。

def _get_conn(self):
    return httplib.HTTPConnection("%s:%d" % (self.host, self.port))
将最后一行更改为

return httplib.HTTPConnection("%s:%d" % (self.host, self.port), timeout=10)

我想我的答案还是对的。然而,另一种可能性是,另一端的连接永远不会关闭。Readline应该会一直阻塞,直到数据到达。您可能有网络问题,或者您的协议本身正在暂停,以至于远程服务器没有向您发送您期望的内容。这不是应该通过超时来解决的吗?为什么超时常常从未发生?我认为这可能在连接本身方面是正确的,但我不确定等待数据是否正确。
return httplib.HTTPConnection("%s:%d" % (self.host, self.port), timeout=10)