使用Popen()无法识别卷曲

时间:2013-06-26 10:53:45

标签: python windows curl python-2.7

p = Popen(["curl", "http://localhost:8983/solr/update/json?commit=true", "--data-binary", "@solrData.json", "-H", "Content-type:application/json"], cwd=r"C:/Users/SOLR/docs", shell=True)

这是我现在正在使用的代码,我得到卷曲无法识别的错误。 当我在solrData.json文件所在的同一目录中运行命令时:

curl "http://localhost:8983/solr/update/json?commit=true" --data-binary @solrData.json -H "Content-type:application/json"

它完美运行。卷曲在系统路径中,并且在那里工作。 另外作为比较,这很好用:

p = Popen("java -jar post.jar solrData.xml", cwd=r"C:/Users/SOLR/docs")

修改

    import requests
# open the file to upload
        with open('C:/Users/SOLR/docs/solrData.json', 'rb') as fin:
            # execute the post request
            headers = {'Content-type': 'application/json'}
            r = requests.post("http://localhost:8983/solr/update/json", params=dict(commit="true"), headers=headers, data=fin.read())

这是有效的解决方案。谢谢zmo和Martijn Pieters的帮助。

2 个答案:

答案 0 :(得分:2)

您正在传递参数的列表,但请设置shell=True。关闭后者(删除参数,False是默认值)并让Python处理命令:

p = Popen(["curl", "http://localhost:8983/solr/update/json?commit=true", "--data-binary", "@solrData.json", "-H", "Content-type:application/json"], cwd=r"C:/Users/SOLR/docs")

请注意,安装python-requests库并从Python完成整个任务会非常简单:

import requests

with open('C:/Users/SOLR/docs/solrData.json', 'r') as solrdata:
    r = requests.post('http://localhost:8983/solr/update/json?commit=true',
        data=solrdata, headers={'Content-type': 'application/json'})

答案 1 :(得分:0)

来自Popen manpage

  

在Unix上,shell = True,shell默认为/ bin / sh。如果args是一个字符串,则该字符串指定要通过shell执行的命令。这意味着字符串的格式必须与在shell提示符下键入时完全相同。这包括,例如,引用或反斜杠转义带有空格的文件名。如果args是一个序列,则第一个项指定命令字符串,并且任何其他项将被视为shell本身的附加参数。也就是说,Popen相当于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])
  

在具有shell = True的Windows上,COMSPEC环境变量指定默认shell。您需要在Windows上指定shell = True的唯一时间是您希望执行的命令是否内置到shell中(例如dir或copy)。您不需要shell = True来运行批处理文件或基于控制台的可执行文件。

所以你需要发出以下命令:

p = Popen(["curl", "http://localhost:8983/solr/update/json?commit=true", "--data-binary", "@solrData.json", "-H", "Content-type:application/json"], cwd=r"C:/Users/SOLR/docs", shell=False)

但为什么要使用子进程来使用curl,而你有pycurl库可以更容易地使用curl?这是受the file upload example启发的代码:

import os
import pycurl
import cStringIO

# here's a handler to expose the read_callback method
class FileReader:
    def __init__(self, fp):
        self.fp = fp
    def read_callback(self, size):
        return self.fp.read(size)

# here's a buffer to handle the output of the pycurl request
buf = cStringIO.StringIO()

# we open the file
with open('solrData.json', 'rb') as fin:
    # get its size
    filesize = os.path.getsize('solrData.json')

    # initiates curl
    c = pycurl.Curl()

    # setup curl (url, as a post request, file upload size and content, content-type and output buffer)
    c.setopt(c.URL, 'http://localhost:8983/solr/update/json?commit=true')
    c.setopt(pycurl.POST, 1)
    c.setopt(pycurl.POSTFIELDSIZE, filesize)
    c.setopt(pycurl.READFUNCTION, FileReader(f).read_callback)
    c.setopt(pycurl.HTTPHEADER, ["Content-type: application/json"])
    c.setopt(c.WRITEFUNCTION, buf.write)

    # we execute the query
    c.perform()

    # and write the result of the query
    with open('C:/Users/SOLR/docs/result.json') as f:    
        f.write(buf.getvalue())
    # and finally we close the buffer
    buf.close()

甚至比使用pycurl更简单,您可以使用requests库:

import requests

# open the file to upload
with open('solrData.json', 'rb') as fin:
    # execute the post request
    headers = {'Content-type': 'application/json'}
    r = requests.post("http://httpbin.org/get", params=dict(commit=True), headers=headers, data=fin.read())
    # write the result
    with open('C:/Users/SOLR/docs') as f:
        f.write(f.text) # write the json data in text file
        print f.json() # print the json content as python datatypes

HTH