Wykonaj polecenie curl w skrypcie Pythona

Próbuję wykonać polecenie curl w skrypcie Pythona.

Jeśli zrobię to w terminalu, wygląda to tak:

curl -X POST -d  '{"nw_src": "10.0.0.1/32", "nw_dst": "10.0.0.2/32", "nw_proto": "ICMP", "actions": "ALLOW", "priority": "10"}' http://localhost:8080/firewall/rules/0000000000000001

Widziałem zalecenia dotyczące stosowania pycurl, ale nie mogłem wymyślić, jak zastosować go do mojego.

Próbowałem użyć:

subprocess.call([
    'curl',
    '-X',
    'POST',
    '-d',
    flow_x,
    'http://localhost:8080/firewall/rules/0000000000000001'
])
I to działa, ale czy jest lepszy sposób?
Author: OJFord, 2014-09-23

6 answers

Możesz użyć urllib, jak powiedział @roippi:

import urllib2
data = '{"nw_src": "10.0.0.1/32", "nw_dst": "10.0.0.2/32", "nw_proto": "ICMP", "actions": "ALLOW", "priority": "10"}'
url = 'http://localhost:8080/firewall/rules/0000000000000001'
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
f = urllib2.urlopen(req)
for x in f:
    print(x)
f.close()
 43
Author: Uxio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-23 17:04:04

Nie! Wiem, tego nikt nie chce. Ale jeśli coś jest warte zrobienia, to jest warte zrobienia dobrze , prawda?

To wydaje się być dobrym pomysłem, prawdopodobnie wynika z dość szerokiego błędnego przekonania, że polecenia powłoki takie jak curl to coś innego niż same programy.

Więc to, o co pytasz, to " jak uruchomić ten inny program, z mojego programu, tylko po to, aby zrobić marne małe żądanie internetowe?". To szaleństwo, musi być lepszy sposób. prawda?

Odpowiedź Uxio Działa, jasne. Ale to nie wygląda bardzo Pythonic , prawda? To dużo pracy, jak na jedną małą prośbę. Python ma być o lataniu ! Każdy, kto pisze, że prawdopodobnie chce tylko call ' D curl!


To działa, ale czy jest lepszy sposób?

Tak, tam jest lepszy sposób!

Wnioski: HTTP dla ludzi

Nie powinno tak być. Nie w Pythonie.

Wejdźmy na tę stronę:

import requests
res = requests.get('https://stackoverflow.com/questions/26000336')

To jest to, naprawdę! Następnie masz wyjście raw res.text lub res.json(), res.headers itd.

Możesz zobaczyć dokumenty (linkowane powyżej), aby uzyskać szczegóły dotyczące ustawiania wszystkich opcji, ponieważ domyślam się, że OP już ruszył, a Ty - czytelnik - prawdopodobnie potrzebujesz innych.

Ale, na przykład, to tak proste jak:

url     = 'http://example.tld'
payload = { 'key' : 'val' }
headers = {}
res = requests.post(url, data=payload, headers=headers)

Możesz nawet użyć ładnego pythonowego dict do dostarczenia ciągu zapytania w żądaniu GET z params={}.

Proste i eleganckie. Zachowaj spokój i leć dalej.
 171
Author: OJFord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Jeśli nie zmieniasz zbytnio polecenia curl, możesz również bezpośrednio wywołać polecenie curl

import shlex
cmd = '''curl -X POST -d  '{"nw_src": "10.0.0.1/32", "nw_dst": "10.0.0.2/32", "nw_proto": "ICMP", "actions": "ALLOW", "priority": "10"}' http://localhost:8080/firewall/rules/0000000000000001'''
args = shlex.split(cmd)
process = subprocess.Popen(args, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
 30
Author: hyades,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 18:38:54

Użyj tego narzędzia (hosted here za darmo), aby przekonwertować polecenie curl na odpowiedni kod zapytań Pythona:

Przykład: To,

curl 'https://www.example.com/' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Origin: https://www.example.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: SESSID=ABCDEF' --data-binary 'Pathfinder' --compressed

Zostaje zamienione na:

import requests

cookies = {
    'SESSID': 'ABCDEF',
}

headers = {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'Origin': 'https://www.example.com',
    'Accept-Encoding': 'gzip, deflate, br',
}

data = 'Pathfinder'

response = requests.post('https://www.example.com/', headers=headers, cookies=cookies, data=data)
 26
Author: Nitin Nain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-08 07:13:06

Spróbuj z podprocesem

CurlUrl="curl 'https://www.example.com/' -H 'Connection: keep-alive' -H 'Cache- 
          Control: max-age=0' -H 'Origin: https://www.example.com' -H 'Accept-Encoding: 
          gzip, deflate, br' -H 'Cookie: SESSID=ABCDEF' --data-binary 'Pathfinder' -- 
          compressed"

Użyj getstatusoutput do przechowywania wyników

status, output = subprocess.getstatusoutput(CurlUrl)
 5
Author: Ramesh Ponnusamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-04 11:12:26

Przeformułowanie jednej z odpowiedzi w tym poście, zamiast używania cmd.split (). Spróbuj użyć:

import shlex

args = shlex.split(cmd)

Następnie podaj args do podprocesu.Popen.

Sprawdź ten dokument, aby uzyskać więcej informacji: https://docs.python.org/2/library/subprocess.html#popen-constructor

 2
Author: Ganesh prasad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 09:53:03