Reputation: 1079
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)
This the code I am using right now, and I get the error that curl is not recognized. When I run the command in the same dir where the solrData.json file is:
curl "http://localhost:8983/solr/update/json?commit=true" --data-binary @solrData.json -H "Content-type:application/json"
it runs perfectly. Curl is in the system path and there everthing works. Also as a comparison this works just fine:
p = Popen("java -jar post.jar solrData.xml", cwd=r"C:/Users/SOLR/docs")
EDIT
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())
This is the solution that works. Thank you zmo and Martijn Pieters for your help.
Upvotes: 1
Views: 2132
Reputation: 1121844
You are passing in a list of arguments, but set shell=True
. Switch off the latter (remove the argument, False
is the default) and let Python handle the command:
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")
Note that it'll be vastly simpler to install the python-requests
library and do the whole task from Python with minimal fuss:
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'})
Upvotes: 2
Reputation: 24812
from Popen manpage:
On Unix with shell=True, the shell defaults to /bin/sh. If args is a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
On Windows with shell=True, the COMSPEC environment variable specifies the default shell. The only time you need to specify shell=True on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not need shell=True to run a batch file or console-based executable.
So you need to issue the following command:
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)
but why do you want to use subprocess to use curl, whereas you have the pycurl
library that makes it easier to use curl? Here's a code inspired by 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()
or even simpler than using pycurl
, you can use the requests
library:
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
Upvotes: 0