&引用;select()中的filedescriptor超出范围;使用python时';带rsync的s子进程

&引用;select()中的filedescriptor超出范围;使用python时';带rsync的s子进程,python,subprocess,rsync,Python,Subprocess,Rsync,下面的代码用于将上传的图片同步到其他位置。它可以工作,但经过一段时间(大约10天)后,服务不可用,显示错误:“filedescriptor超出select()中的范围”,但重新启动服务解决了问题 # sync.py def sync_file(source_pic, hashval, retry_num=3): pic_path = os.path.join(gen_dir(hashval), os.path.split(source_pic)[1]) filename =

下面的代码用于将上传的图片同步到其他位置。它可以工作,但经过一段时间(大约10天)后,服务不可用,显示错误:“filedescriptor超出select()中的范围”,但重新启动服务解决了问题

# sync.py

def sync_file(source_pic, hashval, retry_num=3):

    pic_path = os.path.join(gen_dir(hashval), os.path.split(source_pic)[1])
    filename = tempfile.mkstemp()[1]
    with open(filename, 'w') as f:
        f.write(pic_path)

    for sync_path in options.sync_paths:
        try_num = 0
        rsync_cmd = ['rsync','-au', '--files-from='+filename, options.pic_path, sync_path]

        while try_num < retry_num:
            proc = subprocess.Popen(rsync_cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout_value, stderr_value = proc.communicate()

            if len(stderr_value) != 0:
                logger.error('sync failed: %s' % stderr_value)
                try_num = try_num + 1
                #raise UploadException('sync failed')
            else:
                break

    os.remove(filename)

是否存在导致错误的未关闭文件描述符?子流程似乎没有关闭文件描述符,因此当它运行1024次时,文件描述符超出范围。(我们使用的是python 2.6,子流程被迫使用select.select(),即使epoll可用,它也限制1024个文件描述符)

您可以手动关闭文件描述符。调用
communicate
后,调用
proc.stderr.close()
proc.stdout.close()

在Python 2.7之前,使用
ulimit-n
启用 与大量子流程的通信仍然可以监视 一次只有1024个文件描述符,这导致了异常:

ValueError: filedescriptor out of range in select()
这是由于子流程模块使用
select
系统调用造成的。 该模块现在使用
轮询
系统调用,消除了此限制


可能的修复方法:使用Python2.7+,或者使用
poll

对代码进行后端口处理,这实际上解决了问题吗?我查看了
子流程
的源代码,看起来描述符应该在
\u communicate
中自动关闭。我同意,它们应该是。但出于某种原因,在你的情况下,他们不是。@DavidSchwartz不走运:(在运行了一天之后,仍然有相同的错误。然后我打赌其他一些代码正在泄漏文件描述符,最终导致此代码失败。使用列出进程已打开的文件的工具可能会有所帮助。给代码几个小时,然后运行该工具。我也遇到了同样的问题-你解决了吗,@limboy?最后我删除了PIPE在打开时重定向,并检查
proc.returnval
,它似乎可以工作。
ValueError: filedescriptor out of range in select()