V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
wikinee
V2EX  ›  Python

Python 拷贝大文件分片大小问题

  •  
  •   wikinee · 2019-06-01 14:37:47 +08:00 · 2419 次点击
    这是一个创建于 2030 天前的主题,其中的信息可能已经有所发展或是发生改变。

    python 拷贝大文件一般套路是:

    with open(src_file, "rb") as fr, open(dst_file, 'wb') as fw:  # fr 读文件
        while True:
            data = fr.read(4096)
            if not data:
                break
            fw.write(data)
    

    后面跟一些异常处理,4096 这个是 4 KB,这个大小受什么因素影响?

    写 1 * 1024 * 1024 行吗?我感觉性能完全够啊

    16 条回复    2019-06-03 15:54:43 +08:00
    msg7086
        1
    msg7086  
       2019-06-01 15:08:46 +08:00
    1MB 当然可以。4KB 很可能就是随便写的一个数。

    但是一般不会用 Python 去追求性能。高性能复制大文件还是直接走系统工具比较好吧。
    swulling
        2
    swulling  
       2019-06-01 15:17:35 +08:00 via iPhone
    为啥不用标准库 shutil,搞这种没人用的所谓套路
    clino
        3
    clino  
       2019-06-01 15:43:36 +08:00 via Android
    自己对比测试一下不就知道了
    wikinee
        4
    wikinee  
    OP
       2019-06-01 16:01:11 +08:00
    @msg7086 我再看看。
    @swulling 即使是 shutil 也有缓存大小参数的,这不跟这问题一样吗
    @clino 我自己测试打印时间倒是不难,但是害怕系统调度之类的其他因素会影响到结果
    clino
        5
    clino  
       2019-06-01 17:07:08 +08:00 via Android
    怕受随机因素影响就多做几次嘛
    zeddit
        6
    zeddit  
       2019-06-01 17:13:35 +08:00 via Android
    文件系统 block size 一般是 4k 吧
    scriptB0y
        7
    scriptB0y  
       2019-06-01 17:22:15 +08:00
    @msg7086
    @wikinee

    4KB 不是随机的一个数,Block device 的读操作是按照 block size 来的,读操作按照 block size align 才会更快( size 是 block size 的倍数)。
    scriptB0y
        8
    scriptB0y  
       2019-06-01 17:23:49 +08:00
    我写了一坨,但是后面的内容不知道为啥就是在 V2EX 发不出来,链接也发不出来...

    我贴下 gist 链接转成的 base64 吧,查看方式:

    echo aHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vbGFpeGludGFvLzE0MTJmYTAwOTg5M2VkNDYwMGNmMTE0OGVkMDRhOWIxCg== | base64 -D

    希望你能解答你的疑惑。
    iwtbauh
        9
    iwtbauh  
       2019-06-01 17:50:31 +08:00 via Android   ❤️ 2
    和 block size 没有关系,你读的文件早就中间有文件系统层

    应用程序 --- 文件系统层 --- 块设备层 --- scsi/nvme/mtd.... --- 硬件

    如果你的程序是直接读写块设备而不是文件系统(常见的有镜像烧写软件),再考虑 block size 的问题。

    直接读写文件时,文件系统会处理好这些低级细节并执行缓冲和缓存。

    为什么这个值要大:

    因为 IO 操作(不仅 IO 操作,是全部的系统调用)是很消耗 CPU 的(涉及特权级别切换等耗时操作,特别是 Intel 漏洞使这方面更加剧了)。对于一个文件而言,缓冲区越大意味着调用系统调用的次数越少。
    msg7086
        10
    msg7086  
       2019-06-02 02:48:06 +08:00
    @scriptB0y 不过 block size 不一定是 4K 吧。
    fuzhuo233
        11
    fuzhuo233  
       2019-06-02 08:07:59 +08:00
    4k 是 Linux 的 page size 啊,这是文件缓存层层读文件的最小单位,即使应用层只读一个字节真实也会加载一个页缓存下来。少于一个 page 读多次会浪费 cpu 时间。详询 File Page Cache
    scriptB0y
        12
    scriptB0y  
       2019-06-02 10:08:11 +08:00
    @msg7086 嗯,不一定。 不过一般是 4k,我那个链接后面有说可以用 stat 看 block size,只要是 block size 的倍数就可以
    NoAnyLove
        13
    NoAnyLove  
       2019-06-02 11:33:42 +08:00
    正确的拷贝大文件的正确套路是。。。。。有系统 API 就直接用系统 API,cpython/blob/master/Lib/shutil.py#L227
    NoAnyLove
        14
    NoAnyLove  
       2019-06-02 11:34:24 +08:00
    发个 github 链接需要验证手机号码?这是啥套路?
    lowman
        15
    lowman  
       2019-06-03 11:13:21 +08:00
    wikinee
        16
    wikinee  
    OP
       2019-06-03 15:54:43 +08:00
    @lowman 感谢回复。
    如果不是需要知道每一行内容的话,rb 速率比 r 高,而且安全一些,
    因为 r 遇到一些特殊字符还有可能提前退出。
    另外这边讨论的是拷贝不是读取[捂脸]
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1110 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:34 · PVG 02:34 · LAX 10:34 · JFK 13:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.