在python中传递类实例来代替文件

2024-09-28 22:36:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我找到了这段代码here,它允许我从一个在线zip文件下载一个文件。它奇迹般地工作,但我不明白它是如何工作的,尤其是class是如何工作的(我只对class有一些基本的了解)。我简化了一点原始代码得到下面的MWE。在

import zipfile
import urllib2

DEBUG = True
def HTTPGetFileSize(url):
  request = urllib2.Request(url)
  page = urllib2.urlopen(request)
  size = page.headers['content-length']
  page.close()
  return int(size)

def HTTPGetPartialData(url, f, t):
  request = urllib2.Request(url)
  request.headers['range'] = 'bytes=%u-%u' % (f, t)
  partial_page = urllib2.urlopen(request)
  partial_data = partial_page.read()
  partial_page.close()
  return partial_data

class MyFileWrapper:
  def __init__(self, url):
    self.url = url
    self.position = 0
    self.total_size = HTTPGetFileSize(url)

  def seek(self, offset, whence):
    if whence == 0:
      self.position = offset
    elif whence == 1:
      self.position += offset
    elif whence == 2:
      self.position = self.total_size + offset

    if DEBUG==True:
      print "seek: (%u) %u -> %u" % (whence, offset, self.position)
    pass

  def tell(self):
    if DEBUG==True:    
      print "tell: -> %u" % self.position
    return self.position

  def read(self, amount=-1):
    if amount == -1:
      amount = self.total_size - self.position
    d = HTTPGetPartialData(self.url, self.position, self.position + amount - 1)
    self.position += len(d)
    if DEBUG==True:
      print "read: %u %u -> %u" % (self.position - len(d), amount, self.position)
    return d

url = 'http://the.url.that/contains/the/zipfiles.zip'
filename = 'the_name_of_the_file_I_need.csv'
f = MyFileWrapper(url)
print "class like object f is constructed"
z = zipfile.ZipFile(f)
print "f is read by zipfile and passed to z"
content = z.open(filename)
print "open filename, pass to content"
print content.read()

我有很多问题,但我主要困惑于:

  1. 我的输入filename是如何进入所有函数的?在
  2. 这段代码中函数的流程/顺序是什么?似乎在运行tell函数之后,代码又回到了seek函数。在
  3. 如何初始化和更新offset和{}?在

感谢任何帮助。在

编辑:我包括代码的调试版本,下面是一个示例测试的输出:

^{pr2}$

Tags: 代码selfurlreadsizeifrequestdef
2条回答

这是Python的“duck typing”方法的一个主要示例。为了解释这一点,让我们首先从程序员的角度考虑一下文件实际上是什么:

  • 文件是可以读取并向程序传递字节的内容。在
  • 文件有一个长度(在文件的生命周期中可能会改变,但在任何时间点,它都有一个长度)。在
  • 有些文件可以写入,但有些不能写入:CD/DVD/Bluray上的文件是真正的“只读”文件,但仍然是一个文件。在

示例中的代码提供了一个class,它实现了一个read方法,最后返回字节,因此可以像Python中的普通文件对象一样对待它(如果它有一个read方法,那么它就是一个文件!)在

考虑这个最小的例子:

class SimpleFile(object):
    def read(self):
        return b"a,b,c,d"

class SimpleFileUser(object):
    def __init__(self, f):
        self.f = f

    def use_file(self):
        print(self.f.read())

sf = SimpleFile()
sfu_1 = SimpleFileUser(sf)
sfu_1.use_file()

real_file = open('test.txt')
sfu_2 = SimpleFileUser(real_file)
sfu_2.use_file()

SimpleFileUser可以将任何内容用作实现read方法的文件。它可以是open返回的file对象,也可以是SimpleFile类的实例,因为这个类还提供了一个read方法。在

MyFileWrapper实现了允许您访问可通过HTTP访问的文件的函数。因此,它提供函数tell文件中的当前位置,seek(跳转)到文件中的另一个位置,以及read文件中的实际数据。本例中的文件是通过HTTP访问的。如何调用方法取决于ZipFile。如果在原始代码中使用DEBUG变量,您可以看到ZipFile实际在做什么来读取数据。在

offsetwhence只是seek函数的参数。{a2:}是仿照a2建模的。文件/HTTP可访问内容中的当前位置存储在成员变量self.position

定义了seektell方法,通过将文件指针设置到文件末尾(seek(2, 0))并获得文件指针位置(tell),使zipfile类能够确定文件大小。在

  1. how does my input filename ever get into all the functions?

没有。它只传递到ZipFile中。此代码中的函数未使用文件名。在

  1. what is the flow/order of the functions in this piece of codes? It seems after running tell function, the codes go back to seek function again.

没有具体的命令。我不知道你在问什么。在

  1. How are offset and whence initialized and updated?

在ZipFile中,通过ZipFile代码。在

这段代码的作用是包装一个在线文件,这样只下载它实际读取的部分。其余的魔法行为是标准的。有趣的是read()方法。在

相关问题 更多 >