Why is Django FieldFIle readline() returning the hex version of a text file?(为什么Django FieldFIle Readline()返回十六进制版本的文本文件?)
问题描述
有奇怪的问题。
我有一个Django应用程序,它打开一个文件(表示为DjangoFieldFile
),并使用readline()
读取每一行,如下所示:
with file.open(mode='r') as f:
row = f.readline()
# do something with row...
该文件为文本,采用UTF-8编码,行以
结尾。
问题是每一行都被读取为字符串的十六进制表示形式,因此我得到的不是"Hello",而是"48656c6c6f"。
一些奇怪的事情:
它以前工作正常,但在某个时候被更新破坏了(我尝试回滚到以前的提交,但它仍然不稳定,所以可能是依赖项已经更新,而不是我的
requirements.txt
中的内容)。在我的测试中遗漏了它,因为它位于应用程序中很少使用的部分。如果我使用
readlines()
而不是readline()
读取相同的文件,我会看到[b'...']
中包含的文件的正确字符串表示形式
如果我直接使用Python
open()
和readline()
从解释器读取文件,则文件可以正常读取使用
mode='rt'
强制文本模式不会改变行为,mode='rb'
文件存储在mini存储桶中,因此默认存储是
storages.backends.s3boto3.S3Boto3Storage
fromdjango-storages
,而不是默认的Django存储类。这意味着boto3
、botocore
和s3fs
也混合在一起,这给我的调试带来了更大的困惑。
抓挠我的头,不知道为什么以前这样做有效,我做错了什么。
环境是在Docker容器中运行的Python3.8、Django 2.2.8和3.0(结果相同)。
编辑
让我指出,解决此问题的方法只需使用
row = f.readline().decode()
但我还是想弄清楚发生了什么事。
编辑%2
此外,FieldFile.open()将文件读取为二进制文件,而普通的Python Open()将文件读取为文本文件。
推荐答案
这似乎非常奇怪。 我想你在尝试下面的答案后会立即看到解决方案(如果确实无济于事,我会更新我的答案或删除它,但我很有信心)
假设有一些代码,即monkeypatting file.open或Django视图函数。
我的建议是:
从made.py runserver开始您的代码 将以下代码添加到made.py(作为第一行)import file
print("ID of file.open at manage startup is", id(file.open)
然后将代码直接添加到视图file.open
上方的一行
print("ID of file.open before opening is", id(file.open)
如果这两个ID不同,那么一定有什么东西篡改了您的打开函数。 如果两者相同,则问题一定出在其他地方。
如果您没有看到这两个打印的输出,则可能是某些东西破坏了您的视图。
如果这不起作用,则尝试使用open()
而不是file.open()
您使用file.open()
附录1:
那么您所说的是,该文件是一个类的对象实例,它是一个Filefield吗? 在任何情况下,您都可以获取文件的名称并使用正常的open()
打开它,以查看是只有file.open()
才做有趣的事情,还是open()
也是以这种奇怪的方式读取它。
您是使用cat filename
从命令行打开文件(还是使用type filename
在Windows下打开文件?
如果这不起作用,我们可以在正在执行的源代码的每一行后面添加跟踪。
附录2:
如果您无法在manage.py runserver
中尝试此操作,如果您尝试使用manage.py shell
读取文件,会发生什么情况?
只需打开外壳并键入类似以下内容:
from <your_application>.models import <YourModel>
entry = <YourModel>.objects.get(id=<idofentry>)
line1 = entry.<filefieldname>.open("r").read().split("
")[0]
print("line1 = %r" % line1)
如果仍不确定(但仅当您可以用命令行管理程序重现该问题时),则创建一个包含行的小文件。
from <your_application>.models import <YourModel>
entry = <YourModel>.objects.get(id=<idofentry>)
import pdb; pdb.set_trace()
line1 = entry.<filefieldname>.open("r").read().split("
")[0]
print("line1 = %r" % line1)
并从命令行管理程序导入它。 代码应该进入调试器,现在您可以单步通过打开函数,并查看您是否在某个monkeypatch中使用了类似的奇怪函数。
这篇关于为什么Django FieldFIle Readline()返回十六进制版本的文本文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么Django FieldFIle Readline()返回十六进制版本的
基础教程推荐
- 何时使用 os.name、sys.platform 或 platform.system? 2022-01-01
- 用于分类数据的跳跃记号标签 2022-01-01
- 在 Python 中,如果我在一个“with"中返回.块,文件还会关闭吗? 2022-01-01
- Python kivy 入口点 inflateRest2 无法定位 libpng16-16.dll 2022-01-01
- 如何让 python 脚本监听来自另一个脚本的输入 2022-01-01
- Dask.array.套用_沿_轴:由于额外的元素([1]),使用dask.array的每一行作为另一个函数的输入失败 2022-01-01
- 线程时出现 msgbox 错误,GUI 块 2022-01-01
- 如何在海运重新绘制中自定义标题和y标签 2022-01-01
- 使用PyInstaller后在Windows中打开可执行文件时出错 2022-01-01
- 筛选NumPy数组 2022-01-01