(原创)python的字符串读写和二进制读写

python的文本读写和二进制读写

  • python的文本读写和二进制读写
    • 字符串读写和二进制读写
    • 问题代码复现
笔者在之前的文档里面提出过,scrapy框架本身存在大文件下载的问题,因此产生了改造scrapy的想法,这里在修改下载模块(FilesPipeline)的时候遇到了文本读写和二进制读写的问题。

(scrapy具体bug见笔者的另外一两博客:scrapy的MemoryError(续),scrapy改造过程中踩过的坑(暂未发表))
上上周结束的时候,实验室的师兄说组里的爬虫系统从应用市场里爬取下来的PE文件(exe和dll)无法再次上传和下载,每次重新下载之后的文件只有几个k大小。我看了他的源代码之后发现,其实也是因为字符串读导致上传的时候发生了截断。


字符串读写和二进制读写 :

python的文件读写模块十分的方便,加上with as表达式这样强大的工具,更是用几行代码就可以完成文件读写的功能。

with open('file.txt','rw') as f:
   f.read()
   #f.write('hello python')

其中open方法的第二个参数则是允许的文件操作,一般来说为了文件安全,遵循最小操作原则,即需要什么操作,就仅允许哪类操作(《windows via c++》)
而我们今天要关注的是’b’这个关键词,如果open的第二个参数不加’b’这个选项,则被判定为字符串读写,否则视为二进制读写。

这两者是存在区别的(敲黑板)

二进制读是把整个文件按照字节进行读取一直到文件结束(EOF),不考虑其具体内容。
字符串读则是把文件视为一个很长的字符串,需要处理其中的换行符’\n’,结束符’\0’,转义字符等问题。

问题代码复现:

最初的scrapy修改过程中的代码是这样的:

class _ResponseReader(protocol.Protocol):

    def __init__(self, finished, txresponse, request, maxsize, warnsize,
                 fail_on_dataloss,giant_file):
        self._finished = finished
        self._txresponse = txresponse
        self._request = request
        self._maxsize  = maxsize
        self._warnsize  = warnsize
        self._fail_on_dataloss = fail_on_dataloss
        self._fail_on_dataloss_warned = False
        self._reached_warnsize = False
        self._bytes_received = 0
        self._giant_file = giant_file
        self.giant_file_path = ""
        if giant_file==1:
          #  self._bodybuf = BytesIO()  
            self.giant_file_path =  self.getabspath(self.file_path(request.url),request.store_path)
            dir_name = os.path.dirname(self.giant_file_path)
            if not os.path.exists(dir_name):
                os.makedirs(dir_name)
            f =  open(self.giant_file_path,'w') 
            self._bodybuf = f

        else:
            self._bodybuf = BytesIO()

注意倒数第四行,这里写入文件的方式是’w’,不是’wb’,因此遇到了PE文件下载之后无法打开,打开之后报错的问题。而修改方法就是改成’wb’。

而上面师兄的问题也是这样的,在进行上传的时候采用了’r’的读入方式,而不是’rb’,这里导致了下载的PE文件只有几个k,无法读写。

你可能感兴趣的:(python&爬虫)