سؤال

هل من الممكن استخدام 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top