使用Python模仿檔案行為

华科云商小雪發表於2024-04-15

在Python中,你可以透過檔案操作函式(如 open() 函式)以及模擬輸入輸出流的庫(如 io 模組)來模擬檔案行為。下面是一些示例,展示瞭如何使用這些工具在Python中模擬檔案行為。

1、問題背景

在編寫一個指令碼時,需要將SQL資料庫中某些表的列轉儲到檔案,然後透過FTP傳輸。由於轉儲的內容可能非常龐大,因此設計了一個方案,即建立一個MysSQLFakeFile,該檔案在readline方法中逐行查詢游標,並將其傳遞給ftplib.FTP.storlines。

以下是實現程式碼:


import 
ftplib

import MySQLdb

def MySQLFakeFile( object):
'''
模擬一個只讀檔案,按需轉儲存表資料
透過將其傳遞給FTP協議,可使轉儲更有效率,而無需將其轉儲到某處並在網路上傳輸
'''
def __init__( self, cursor, delimeter, table_name, query):
self. cursor = cursor
self. delimeter = delimeter
self. table_name = table_name
# 查詢類似於select ... FROM %s
self. cursor. execute( query, table_name)
self. _has_written_index = False
# 檔案屬性
self. closed = False
self. name = table_name + ".csv"
self. encoding = "utf-8"
self. mode = "r"

def close( self):
self. cursor. close()
self. closed = True

def flush( self):
'''空操作'''
pass

def read( self, size):
pass

def readline( self, size):
if not self. _has_written_index:
ret = []
for desc in self. cursor. description:
ret. append( desc[ 0])
self. _has_written_index = True
else:
ret = self. cursor. fetchone()
if not ret:
return None

s = ""
for col in ret:
s += str( col) + self. delimeter
return s + "\n"

def readlines( self, size):
ret = []
line = self. readline()
while line:
ret. append( line)
line = self. readline()

def write( self, string):
raise Exception( "無法寫入MySQLFafeFile")

def writelines( self, lines):
raise Exception( "無法寫入MySQLFafeFile")

db = MySQLdb( "host", "user", "pass", "db")
ftp = ftplib. FTP( "host", "user", "pass")
fakeFile = MySQLFakeFile( db. cursor(), ";", "tableName", "SELECT * FROM %s")
ftp. storlines( "STOR tableName.csv", fakeFile)

然而,執行這段程式碼時卻產生了以下錯誤:

Traceback (most recent call last):

File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/ftplib.py", line 496, in storlines
if len(buf) > self.maxline:
TypeError: object of type 'NoneType' has no len()

2、解決方案

經過分析,發現問題出在readline方法中,當到達行尾時,它返回None而不是空字串("")。同時,readlines方法也沒有返回任何內容。

因此,對readline方法和readlines方法進行了修改,如下:


def 
readline(
self, 
size):

if not self. _has_written_index:
ret = []
for desc in self. cursor. description:
ret. append( desc[ 0])
self. _has_written_index = True
else:
ret = self. cursor. fetchone()
if not ret:
return None

s = ""
for col in ret:
s += str( col) + self. delimeter
return s + "\n"

def readlines( self, size):
ret = []
while True:
line = self. readline()
if not line:
break
ret. append( line)
return ret

修改後的程式碼執行正常,可以將表資料透過FTP傳輸到指定檔案中。

在這個示例中,我在使用 io.StringIO 建立了一個記憶體中的檔案物件,並向其中寫入了一些文字。然後我們將檔案指標移動到開頭,讀取內容並列印出來。最後,我們關閉記憶體中的檔案物件。

使用這些方法,我們可以在Python中模擬檔案的行為,並根據需要進行讀寫操作。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70034537/viewspace-3012523/,如需轉載,請註明出處,否則將追究法律責任。

相關文章