【Python】file.read()查找源码之旅

目录

一、前言

二、查找过程

三、file.read()源码(来源:项目文件夹\.venv\Lib\site-packages\PIL\ContainerIO.py)

四、后记

五、file.read()源码(来源:Python安装目录\Lib\_pyio.py)(“正主”)


一、前言

在学习Python的过程中,突然想查看读取文件的read()方法的源码,结果在PyCharm编辑器中按住Ctrl+鼠标左键点击read()方法进去查看,发现啥也没有,就一脸懵……就这儿???

    @abstractmethod
    def read(self, n: int = -1) -> AnyStr:
        pass

看了个寂寞……后面查找各种资料也没找到……(emm……官方文档也不太会查,如果有大佬知道的请指教一二,非常感谢!)后面就一顿乱找。

二、查找过程

1、自己写的Test4.py文件里read()方法:

2、按住Ctrl+鼠标左键点击read()方法进去查看其内部代码:

再按住Ctrl+鼠标左键点击read又回到自己写的Test4.py文件里的read()方法了……然后想着,应该是File或IO相关的文件,于是先定位typing.py的位置,再到附近找找。

3、定位typing.py文件并查找附近的File或IO等文件:

filecmp.py:

fileinput.py:

io.py:

很遗憾,都没有……于是陷入了迷茫……后面又找了typing.py里面的IO类:

根据提示按Ctrl+Alt+F7(有时候要按多次才有反应),出来一大包,然后随便找了个比较“可疑”的write()方法:

来到了typing.pyi:

查找了一下read()方法:

点了个小图标出来一大包,当时心想着一个个去看,应该总能找到:

结果第一个就是,哈哈哈哈哈!

三、file.read()源码(来源:项目文件夹\.venv\Lib\site-packages\PIL\ContainerIO.py)

位置:D:\Projects\code\Python\Study\Test\.venv\Lib\site-packages\PIL\ContainerIO.py

(D:\Projects\code\Python\Study\Test是我的项目文件)

    def read(self, n: int = -1) -> AnyStr:
        """
        Read data.

        :param n: Number of bytes to read. If omitted, zero or negative,
            read until end of region.
        :returns: An 8-bit string.
        """
        if n > 0:
            n = min(n, self.length - self.pos)
        else:
            n = self.length - self.pos
        if n <= 0:  # EOF
            return b"" if "b" in self.fh.mode else ""  # type: ignore[return-value]
        self.pos = self.pos + n
        return self.fh.read(n)

四、后记

不是,谁能想到还有个typing.pyi文件,而且typing.py和typing.pyi这俩哥们儿根本不在一块儿,不在同一个包……

D:\ProgramFiles\Python\Python311\Lib\typing.py

D:\ProgramFiles\JetBrains\PyCharm2024.3.1.1\plugins\python-ce\helpers\typeshed\stdlib\typing.pyi

咱也不知道咋回事儿,总之是找到了源码o(* ̄▽ ̄*)ブ


但是!还没结束!怀着一颗好奇的心,查了一下,ContainerIO.py里面read()方法的源码是图像处理的PIL这个库的,估计之前导入过相关的库,我重新创建一个项目后,直接写读取文件代码,不干其他的,结果就没有ContainerIO.py这玩意儿了,所以说这个源码可能并不准确!

神奇的事情来了!在通过我Ctrl+H全局一顿胡乱搜索read()方法之后,再通过Ctrl+鼠标左键点击typing.py里的read()方法,结果弹出来一大包东西。(?_?)

这里可以选择“Project Files”,点击一下就回到我们自己的项目文件夹里了。之前这里应该默认Project Files,所以查找起来才这么辛苦……

然后找到了第二个源码。

五、file.read()源码(来源:Python安装目录\Lib\_pyio.py)(“正主”)

D:\ProgramFiles\Python\Python311\Lib\_pyio.py

read()和_read_unlocked()方法的源码:

    def read(self, size=None):
        """Read size bytes.

        Returns exactly size bytes of data unless the underlying raw IO
        stream reaches EOF or if the call would block in non-blocking
        mode. If size is negative, read until EOF or until read() would
        block.
        """
        if size is not None and size < -1:
            raise ValueError("invalid number of bytes to read")
        with self._read_lock:
            return self._read_unlocked(size)

    def _read_unlocked(self, n=None):
        nodata_val = b""
        empty_values = (b"", None)
        buf = self._read_buf
        pos = self._read_pos

        # Special case for when the number of bytes to read is unspecified.
        if n is None or n == -1:
            self._reset_read_buf()
            if hasattr(self.raw, 'readall'):
                chunk = self.raw.readall()
                if chunk is None:
                    return buf[pos:] or None
                else:
                    return buf[pos:] + chunk
            chunks = [buf[pos:]]  # Strip the consumed bytes.
            current_size = 0
            while True:
                # Read until EOF or until read() would block.
                chunk = self.raw.read()
                if chunk in empty_values:
                    nodata_val = chunk
                    break
                current_size += len(chunk)
                chunks.append(chunk)
            return b"".join(chunks) or nodata_val

        # The number of bytes to read is specified, return at most n bytes.
        avail = len(buf) - pos  # Length of the available buffered data.
        if n <= avail:
            # Fast path: the data to read is fully buffered.
            self._read_pos += n
            return buf[pos:pos+n]
        # Slow path: read from the stream until enough bytes are read,
        # or until an EOF occurs or until read() would block.
        chunks = [buf[pos:]]
        wanted = max(self.buffer_size, n)
        while avail < n:
            chunk = self.raw.read(wanted)
            if chunk in empty_values:
                nodata_val = chunk
                break
            avail += len(chunk)
            chunks.append(chunk)
        # n is more than avail only when an EOF occurred or when
        # read() would have blocked.
        n = min(n, avail)
        out = b"".join(chunks)
        self._read_buf = out[n:]  # Save the extra data in the buffer.
        self._read_pos = 0
        return out[:n] if out else nodata_val

结案!0(n_n)0

(emm……其实在定位typing.py文件并查找附近的File或IO等文件的时候就很接近真相了,结果走岔路走了😂再往上找找,找到_pyio.py就哦了)

作者:晨曦之光Wing

物联沃分享整理
物联沃-IOTWORD物联网 » 【Python】file.read()查找源码之旅

发表回复