Python调用PowerShell的Invoke-RestMethod时JSON格式转换问题
问题分析与解决方案
现有代码的核心问题
你当前的代码在处理JSON请求体时,手动将双引号替换为\"的方式会导致PowerShell解析错误——因为PowerShell的字符串转义规则和Python不同,嵌套引号的处理逻辑很容易引发格式混乱。另外,用Invoke-Expression解析请求头的方式还存在安全风险。
正确的格式处理方式
1. JSON请求体的安全传递
不需要手动转义JSON中的双引号,推荐两种更可靠的方式:
- 用单引号包裹JSON:PowerShell中,单引号包裹的字符串不会解析内部转义字符,能直接保留JSON的原始格式:
import subprocess import base64 credentials = "login:password" url = 'urlXXXurl' body = '{"id": 4986986, "key": "2df534ee-270b-4ab4-83fb-1b308febacce"}' encoded_creds = base64.b64encode(credentials.encode("ascii")).decode("ascii") headers = f'@{{Authorization = "Basic {encoded_creds}"}}' # 用单引号包裹Body参数,避免引号冲突 command = f'powershell.exe Invoke-RestMethod -Method Post -Uri "{url}" -ContentType application/json -Body \'{body}\' -Headers {headers} -UseBasicParsing' response = subprocess.check_call(command)
- 通过临时文件传递JSON:如果JSON内容复杂或包含特殊字符,将JSON写入临时文件,让PowerShell读取文件内容,彻底避免引号问题:
import subprocess import base64 import tempfile import os credentials = "login:password" url = 'urlXXXurl' body = '{"id": 4986986, "key": "2df534ee-270b-4ab4-83fb-1b308febacce"}' # 创建临时JSON文件 with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as f: f.write(body) temp_path = f.name encoded_creds = base64.b64encode(credentials.encode("ascii")).decode("ascii") headers = f'@{{Authorization = "Basic {encoded_creds}"}}' # PowerShell读取临时文件内容作为请求体 command = f'powershell.exe Invoke-RestMethod -Method Post -Uri "{url}" -ContentType application/json -Body (Get-Content \'{temp_path}\' -Raw) -Headers {headers} -UseBasicParsing' try: response = subprocess.check_call(command) finally: # 执行后删除临时文件 os.unlink(temp_path)
2. 请求头的优化处理
直接构建PowerShell哈希表字符串,完全不需要Invoke-Expression,既安全又简洁:
encoded_creds = base64.b64encode(credentials.encode("ascii")).decode("ascii") headers = f'@{{Authorization = "Basic {encoded_creds}"}}'
3. 更高效的替代方案
既然已经导入了requests库,直接用Python发送请求即可,完全没必要调用PowerShell,能避免跨环境的格式问题,代码也更简洁:
import requests import base64 credentials = "login:password" url = 'urlXXXurl' body = {"id": 4986986, "key": "2df534ee-270b-4ab4-83fb-1b308febacce"} encoded_creds = base64.b64encode(credentials.encode("ascii")).decode("ascii") headers = {"Authorization": f"Basic {encoded_creds}"} response = requests.post(url, json=body, headers=headers) # 可按需查看响应内容 print(response.json())
内容的提问来源于stack exchange,提问作者Takeren
相关产品推荐
相关产品推荐

