django wsgi + Popen + svn checkout



由于某些原因,我需要从django视图签出一个源代码文件夹,为此我使用了'Popen'。

一切都很好,使用django runserver时效果非常好

然而,在我将代码部署到apache2+wsgi之后,Popen无法正常工作。它总是在命令实际完成之前返回。它也没有抛出错误,它只是抛出完整的输出,我检查了签出的文件夹,它们也不完整。

整个svn签出过程大约需要5-6秒,标准输出相当大(大约3000个字符)。

我知道有一个pysvn库,但在过时的ubuntu服务器上安装它似乎很困难。

基本上,这是我现在唯一陷入困境的事情。

我用来调用结账的代码如下:

def run_cmd(argument_list, output_file = None):
    print "arguments", argument_list
    p = subprocess.Popen(argument_list, stdout=subprocess.PIPE)
    content = ""
    while True:
        line = p.stdout.read(50)
        if not line:
            break
        content += line
    if output_file:
        fout = file(output_file, "w")
        fout.write(content)
        fout.close()
    return content

output = run_cmd(["/usr/bin/svn", "--ignore-externals", "co", svn_url, src_folder] )

以下是一些可能有用的信息:

  1. 要检出的文件数:约3000
  2. 签出所需时间:大约5-6秒(仅基于文件的SVN位置)
  3. python版本:2.6.4
  4. django版本:1.1.2
  5. mod-wsgi版本:3.3

我已经坚持了好几个小时了,任何提示都将不胜感激!

谢谢。

好吧,今天又挣扎了3个小时。我终于解决了这个问题。

以下是正在发生的事情,wsgi&popen实际上很好,真正的问题是一些用于签出的源代码文件实际上有特殊字符,这破坏了svn签出过程(出现以下错误)

svn:无法将字符串从"UTF-8"转换为本机编码

wsgi和控制台具有不同的LC_LANG值,这解释了runserver和wsgi之间的不同行为。

最后,我通过修改"/etc/apache2/envars"文件并取消注释以下行来解决问题:

/etc/default/locate

请注意,必须通过"apache2ctl stop"one_answers"apache2ctl start"而不是"apache2ctl-restart"重新启动服务器,才能使设置生效。

实际上,我用pexpect来找出问题,但后来又回到了Popen,因为存在明显的延迟问题。

这是我的run_cmd的最后一段代码,希望它能在未来帮助其他人:

def run_cmd(argument_list, output_file = None):
    print "arguments", argument_list

    #command = " ".join(argument_list)
    #content = pexpect.run(command)
    #if output_file:
        #fout = file(output_file, "w")
        #fout.write(content)
        #fout.close
    #return content
    p = subprocess.Popen(argument_list, bufsize=50, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) #showed error message as well
    content = ""
    while True:
        line = p.stdout.read(50)
        if not line:
            break
        content += line
    #raise Exception(content)   #for debug
    if output_file:
        fout = file(output_file, "w")
        fout.write(content)
        fout.close()
    return content

最新更新