【问题标题】:In Python What is the common interface of readline, readlines, read, etcPython中readline、readlines、read等常用接口是什么
【发布时间】:2021-09-21 11:15:46
【问题描述】:

我正在尝试使用function I came up with,这样我可以添加一个进度条显示文件已读取多少,但是当我这样做时:

file_path = 'file'
f = open(file_path, 'rb')
file_size = os.path.getsize(file_path) 

def new_readline(self, size=-1):
    print(self.tell(), '/', file_size)

f.read = hook(new_readline, f.read)

如果我尝试使用 f.readlines() 读取文件的行,它不会显示任何内容,它只会在我使用 f.readline() 时显示输出。

即使我勾搭f.read,我仍然一无所获。

那么,我可以挂钩的所有数据读取方法调用的通用方法是什么(不一定是 readline 方法,只是它们都调用 self 的东西)?

【问题讨论】:

  • 没有这种常用的方法。也没有理由期待一个通用的方法。
  • (你很幸运,你甚至可以重新分配f.read - 大多数内置类型不允许你这样做。)
  • 所以我必须给所有的读取方法添加一个钩子,哦,好吧,很公平,谢谢你的回复,我知道这是一个奇怪的问题。我只需要求助于他,因为 python openstack SDK 没有提供读取图像上传进度的方法(只能通过流式下载,逐块下载)。
  • 您的替换方法实际上不会读取任何内容,尤其是不会返回请求的内容。为什么您会因为使用它导致阅读无法提供预期的内容而感到困惑?
  • @MisterMiyagi,它不应该替换任何东西,它应该在原始方法之前调用,但它仍然调用原始所以它不需要返回任何东西,它只是一种交互方式每次调用readline()(在这种情况下)时使用该对象。问题是我认为readlines() 在内部使用了readline(),所以如果我在那里添加钩子,那么每次从文件对象代表的文件中读取数据时,无论它如何发生,我的钩子都会被调用。

标签: python file methods


【解决方案1】:

最后我不得不将钩子附加到read() 方法,但它有效!

不管怎样,这里有完整的代码供感兴趣的人参考:

from types import MethodType
import os

ESCAPE = {
    'c': { # colours
        'fg': { # foreground
            'b': '30', # black
            'r': '31', # red
            'g': '32', # green
            'y': '33', # yellow
            'u': '34', # blue
            'p': '35', # purple
            'c': '36', # cyan
            'w': '37', # white
        },
        'bg': { # background
            'b': '40', # black
            'r': '41', # red
            'g': '42', # green
            'y': '43', # yellow
            'u': '44', # blue
            'p': '45', # purple
            'c': '46', # cyan
            'w': '47', # white
        }
    },
    's': { # style
        'n': '0',  # none
        'b': '1',  # bold
        'u': '2',  # underline
        'n1': '3', # negative1
        'n2': '5', # negative2
    },
    't': '\033[{s};{fg};{bg}m', # template 
    'util': {
        'hide': '\033[?25l',
        'show': '\033[?25h',
        'go_up': '\033[{}A',
        'go_down': '\033[{}B',
        'erase_line': '\033[K',
    }
} 


# Open a file but attach an upload progress display if it was requested
def open_file(args, mode='r'):
    f = open(args.file_name, mode)
    if args.progress:
        f.size = os.path.getsize(args.file_name) 
        f.spinner = spinner(
            f"Uploading image({colour(s='b')}{args.file_name}{colour()}) \
as '{colour(s='b')}{args.image_name}{colour()}' -"
        )
        def read_progress(self, size):
            print(
        f"{next(self.spinner)}{next(progress(self.size, step=size, p=self.tell()))}", end='\r'
            )

        f.read = hook(f.read, read_progress)
    return f

# Attach a callback to be executed whenever this method is called
# Note, callback args must match method being hooked
def hook(oldfunc, hookfunk):
    def merged(self, *args, **kwargs):
        hookfunk(self, *args, **kwargs)
        return oldfunc(*args, **kwargs)
    return  MethodType(merged, oldfunc.__self__)

# A spinner with a message, use `next()` to get the next frame
def spinner(msg: str):
    template = f"{colour(fg='p', s='b')}{'{}'}{colour()} {msg}"
    while True:
        for spin in '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏':
            yield template.format(spin)

# Generate a progress bar, use `next()` to get the next progress
def progress(end: int, max_col=80, step=1024, p=1):
    template = f"[{colour(fg='c', s='b')}{'{}'}{colour(fg='w')}{'{}'}{colour()}|{'{}'}]"
    while (p <= end):
        bar = '▇' * int(max_col * p/(end-1))
        togo = '▇' * int(max_col - len(bar))
        perc = "%6.2f %%" % (p/(end-1)*100)
        yield template.format(bar, togo, perc)
        p += step

# Set the colour of the next segment of text
def colour(fg='w', bg='b', s='n'):
    return ESCAPE['t'].format(
            s=ESCAPE['s'][s],
            fg=ESCAPE['c']['fg'][fg],
            bg=ESCAPE['c']['bg'][bg]
    )


附:我意识到每次都重新创建进度条效率不高,但我不知道有什么其他方法可以每次更改 step 值,因为上传速度不是恒定的,我仍然需要它来使用next在其他地方使用。

【讨论】:

    猜你喜欢
    • 2022-12-05
    • 2011-07-01
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2019-05-23
    • 2011-09-08
    相关资源
    最近更新 更多