在请求中发送多部分表单数据时是否需要使用 with 语句?
Do I need to use a with statement when sending multipart form data in requests?
在 Python 的 requests
documentation 中,它建议像这样发送多部分表单数据:
Requests makes it simple to upload Multipart-encoded files:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
同一作者的 This question shows the same behavior. However, this question 使用 with
语句:
with open('data','rb') as payload:
headers = {'content-type': 'application/x-www-form-urlencoded'}
r = requests.post('https://IP_ADDRESS/rest/rest/2', auth=('userid', 'password'),
data=payload, verify=False, headers=headers)
我的直觉是在使用文件时我应该总是使用 with
语句;在这种情况下我是否需要它?需要特别说明的是,我 不是 寻找关于是否使用 with
的建议。我特别指的是与 requests
库的交互,如果我可以像文档暗示的那样省略 with
语句。
是的。使用 with
语句为您处理关闭资源。您应该使用它来正确处理外部资源。
该文档只是试图演示 files
参数的工作原理,而不用过多担心文件是否被关闭。一个更好的例子是
with open('report.xls', 'rb') as f:
r = requests.post(url, files={'file': f})
tl;dr:你的直觉是对的。
没有 with
语句(或明确的 payload.close()
调用),您不会关闭文件。
当然,总是可能您调用的某些函数,将文件作为参数传递,可能close
那个文件。但总的来说,他们不会;而且,特别是 requests.post
没有。 (因为这是非常罕见和不寻常的行为,如果一个函数这样做的话,它可能会被记录下来。但是如果你需要绝对确定,你总是可以测试它——调用函数然后检查 f.closed
——或者阅读来源。)
那么,如果不关闭它会怎样?它只是坐在那里打开,直到垃圾收集器删除文件对象。什么时候发生?好吧,你有一个名为 files
的全局变量,它包含一个包含文件对象的字典。所以文件对象一直是可访问的,直到你退出程序。它永远不会变成垃圾,所以它永远不会被删除,所以文件永远不会关闭,直到你exit
。
由于您没有向文件写入任何内容,因此这不会导致任何可怕的事情,例如当您希望数据位于磁盘上时,未刷新的数据却留在缓冲区中。
但这确实意味着您在浪费资源。 OS 内核必须为每个打开的文件保留某种结构,并且进程需要一些其他东西来引用该内核结构。如果您打开数以千计的文件而不关闭它们,最终,其中一个表会被填满,下次您尝试打开文件时,您会收到有关打开的文件太多的错误。
并且需要处理大量 requests
的程序类型往往正是需要处理数千个文件的程序类型,因此这可能是一个真正的问题。
那么,您需要 此处的with
声明吗?也许不吧。但你肯定想要一个。
在 Python 的 requests
documentation 中,它建议像这样发送多部分表单数据:
Requests makes it simple to upload Multipart-encoded files:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
同一作者的 This question shows the same behavior. However, this question 使用 with
语句:
with open('data','rb') as payload:
headers = {'content-type': 'application/x-www-form-urlencoded'}
r = requests.post('https://IP_ADDRESS/rest/rest/2', auth=('userid', 'password'),
data=payload, verify=False, headers=headers)
我的直觉是在使用文件时我应该总是使用 with
语句;在这种情况下我是否需要它?需要特别说明的是,我 不是 寻找关于是否使用 with
的建议。我特别指的是与 requests
库的交互,如果我可以像文档暗示的那样省略 with
语句。
是的。使用 with
语句为您处理关闭资源。您应该使用它来正确处理外部资源。
该文档只是试图演示 files
参数的工作原理,而不用过多担心文件是否被关闭。一个更好的例子是
with open('report.xls', 'rb') as f:
r = requests.post(url, files={'file': f})
tl;dr:你的直觉是对的。
没有 with
语句(或明确的 payload.close()
调用),您不会关闭文件。
当然,总是可能您调用的某些函数,将文件作为参数传递,可能close
那个文件。但总的来说,他们不会;而且,特别是 requests.post
没有。 (因为这是非常罕见和不寻常的行为,如果一个函数这样做的话,它可能会被记录下来。但是如果你需要绝对确定,你总是可以测试它——调用函数然后检查 f.closed
——或者阅读来源。)
那么,如果不关闭它会怎样?它只是坐在那里打开,直到垃圾收集器删除文件对象。什么时候发生?好吧,你有一个名为 files
的全局变量,它包含一个包含文件对象的字典。所以文件对象一直是可访问的,直到你退出程序。它永远不会变成垃圾,所以它永远不会被删除,所以文件永远不会关闭,直到你exit
。
由于您没有向文件写入任何内容,因此这不会导致任何可怕的事情,例如当您希望数据位于磁盘上时,未刷新的数据却留在缓冲区中。
但这确实意味着您在浪费资源。 OS 内核必须为每个打开的文件保留某种结构,并且进程需要一些其他东西来引用该内核结构。如果您打开数以千计的文件而不关闭它们,最终,其中一个表会被填满,下次您尝试打开文件时,您会收到有关打开的文件太多的错误。
并且需要处理大量 requests
的程序类型往往正是需要处理数千个文件的程序类型,因此这可能是一个真正的问题。
那么,您需要 此处的with
声明吗?也许不吧。但你肯定想要一个。