باستخدام عبارة "مع" لملفات CSV في Python
-
22-07-2019 - |
سؤال
هل من الممكن استخدام with
بيان مباشرة مع ملفات CSV؟ يبدو من الطبيعي أن تكون قادرًا على فعل شيء كهذا:
import csv
with csv.reader(open("myfile.csv")) as reader:
# do things with reader
لكن CSV.Reader لا يوفر __enter__
و __exit__
الطرق ، لذلك هذا لا يعمل. ومع ذلك يمكنني القيام بذلك في خطوتين:
import csv
with open("myfile.csv") as f:
reader = csv.reader(f)
# do things with reader
هل هذه الطريقة الثانية هي الطريقة المثالية للقيام بذلك؟ لماذا لا يجعلون CSV.Reader متوافقًا مباشرة مع البيان؟
المحلول
الاستخدام الأساسي ل with
البيان هو تنظيف آمن من الاستثناء للكائن المستخدم في البيان. with
تأكد من إغلاق الملفات ، يتم إطلاق الأقفال ، يتم استعادة السياقات ، إلخ.
يفعل CSV.Reader هل لديك أشياء للتنظيف في حالة استثناء؟
سأذهب مع:
with open("myfile.csv") as f:
for row in csv.reader(f):
# process row
لا تحتاج إلى إرسال التصحيح للاستخدام csv.reader
و with
بيان معا.
import contextlib
مساعدة في سياق الوظيفة في الوحدة النمطية سياق:
contextmanager(func)
@contextmanager decorator.
الاستخدام النموذجي:
@contextmanager
def some_generator(<arguments>):
<setup>
try:
yield <value>
finally:
<cleanup>
هذا يجعل هذا:
with some_generator(<arguments>) as <variable>:
<body>
أي ما يعادل هذا:
<setup>
try:
<variable> = <value>
<body>
finally:
<cleanup>
إليك مثال ملموس كيف استخدمته: CURSES_SCREEN.
نصائح أخرى
نعم. الطريقة الثانية صحيحة.
لماذا؟ من يعرف. أنت على حق ، ربما يكون تغييرًا سهلاً. إنها ليست أولوية عالية مثل الأشياء الأخرى.
يمكنك بسهولة صنع مجموعة التصحيح الخاصة بك وتقديمها.
المشكلة هي أن CSV.Reader لا يدير سياقًا حقًا. يمكن أن يقبل أي ملف ، وليس مجرد ملف. لذلك لا يتصل بإغلاق مدخلاته (بالمناسبة إذا كان بإمكانك استخدام ContextLib.Closing). لذلك ليس من الواضح ما هو دعم السياق لـ CSV.Reader الذي سيفعله بالفعل.
import csv
class CSV(object):
def __init__(self,path,mode):
self.path = path
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.path,self.mode)
if self.mode == 'r':
return csv.reader(self.file)
elif self.mode == 'w':
return csv.writer(self.file)
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with CSV('data.csv','r') as reader:
for row in reader:
print row
من السهل إنشاء ما تريده باستخدام وظيفة المولد:
import csv
from contextlib import contextmanager
@contextmanager
def opencsv(path):
yield csv.reader(open(path))
with opencsv("myfile.csv") as reader:
# do stuff with your csvreader