【问题标题】:Curl Is Not Recognized , Using Popen()无法识别卷曲,使用 Popen()
【发布时间】:2013-06-26 10:53:44
【问题描述】:
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)

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

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

它运行完美。 Curl 在系统路径中,一切正常。 同样作为比较,这很好用:

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 的帮助。

【问题讨论】:

    标签: python windows curl python-2.7


    【解决方案1】:

    您正在传递一个 list 参数,但设置了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'})
    

    【讨论】:

    • @user2485334:import os; print os.environ['PATH'] 说什么?该路径是否包含curl 所在的目录?
    • @user2485334:在底层,Python 使用CreateProcess call 来执行curl;您可以从链接页面中看到 Windows 将在其中查找命令。
    【解决方案2】:

    来自Popen manpage

    在 shell=True 的 Unix 上,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)
    

    但是为什么要使用 subprocess 来使用 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

    【讨论】:

    • pycurl API 实在是太可怕了;即使通过命令行界面,我也永远无法推荐它。您的文件使用错误; curl 将发布文件的内容(上传),而不是下载。
    • 首先:带有 shell=False 的代码不起作用,仍然给我系统找不到文件错误。其次:我需要给 curl 额外的参数:“--data-binary”、“@solrData.json”、“-H”、“Content-type:application/json” 我将如何使用 pycurl 来做到这一点?跨度>
    • 哦,该死的......我完全同意你对pycurl API 的看法。我只是告诉 OP 他有其他更好的选择,而不是通过subprocess 调用curl 命令。这就是为什么我给了他更好、更优雅的解决方案来使用requests
    • 哦,我误读了 curl 请求。我也在修改我发布文件的答案。
    • @user2485334:废话; SOLR 接受任何格式正确的 HTTP 连接。 curl 只是一个 HTTP 客户端,就像 requests 库一样。您是否真的尝试过我们的建议?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2019-02-16
    • 2012-12-15
    相关资源
    最近更新 更多