ขอให้เป็นวันที่ดี,

ฉันมีปัญหาที่ไฟล์ CSV ส่งไปยัง View และส่งต่อไปในเธรดใหม่สำหรับการประมวลผล บางครั้งปิดก่อนเวลาอันควร และฉันไม่ทราบสาเหตุ ลักษณะการทำงานไม่สม่ำเสมอและเริ่มเกิดขึ้นหลังจากที่ฉันเปลี่ยนไปใช้เธรดใหม่เพื่อประมวลผลไฟล์เท่านั้น

นี่เป็นวิธีดั้งเดิมที่ฉันประมวลผลไฟล์และใช้งานได้ แต่สำหรับไฟล์ขนาดใหญ่ มันทำให้เกิดปัญหาการหมดเวลาในไคลเอนต์:

class LoadCSVFile(APIView):
    permission_class = (IsAuthenticated,)
    parser_classes = [FormParser, MultiPartParser]

    def post(self, request):
        file = request.FILES['file']
        data_set = file.read().decode('utf-8')
        io_string = io.StringIO(data_set)

        for row_data in csv.reader(io_string, delimiter=',', quotechar='"'):
            print('row_data:', row_data)

        return Response({ 'message': 'File received and is currently processing.', 'status_code': status.HTTP_200_OK }, status.HTTP_200_OK)

ดังนั้นฉันจึงประมวลผลไฟล์ในเธรดใหม่ดังนี้:

class LoadCSVFile(APIView):
    permission_class = (IsAuthenticated,)
    parser_classes = [FormParser, MultiPartParser]

    def post(self, request):
        request_handler = RequestHandler(request)
        csv_handler = CSVHandler(request.FILES['file'])

        # Fire and forget the file processing.
        t = threading.Thread(target=request_handler.resolve, kwargs={ 'csv_handler': csv_handler })
        t.start()
        return Response({ 'message': 'File received and is currently processing.', 'status_code': status.HTTP_200_OK }, status.HTTP_200_OK)


class RequestHandler(object):
    def __init__(self, request : Request):
        self.request = request

    def resolve(self, **kwargs):
        csv_handler = kwargs['csv_handler']

        try:
            print('Processing file...')
            csv_handler.process_file()
        except Exception as e:
            print('process_file level error:', e)


class CSVHandler(object):
    def __init__(self, file):
        self.file = file

    def get_reader(self):
        # Error is raised at the following line: "I/O operation on closed file."
        data_set = self.file.read().decode('utf-8')
        io_string = io.StringIO(data_set)
        return csv.reader(io_string, delimiter=',', quotechar='"')

    def process_file(self, **kwargs):
        for row_data in self.get_reader():
            print('row_data:', row_data)

สักพักก็เยี่ยม แต่จากนั้นฉันก็เริ่มสังเกตเห็นข้อผิดพลาดของ I/O เป็นครั้งคราว

  • สิ่งนี้เกิดขึ้นกับไฟล์ขนาดใหญ่ (5,000 บรรทัด) และไฟล์ขนาดเล็ก (2 บรรทัด)
  • ฉันสามารถอัปโหลดได้ 50 ครั้งโดยไม่เห็นข้อผิดพลาด จากนั้นจะเกิดขึ้น 2 หรือ 3 ครั้งติดต่อกัน หรือที่ไหนก็ได้ในระหว่าง
  • ทั้งคำขอถูกบันทึกใน RequestHandler และไฟล์จะถูกบันทึกใน CSVHandler ก่อนที่เธรดจะเริ่มต้น และฉันไม่รู้ว่าจะรักษา InMemoryUploadedFile ให้คงอยู่ได้อย่างไรจนกว่าฉันต้องการ ( csv_handler.get_reader())

ข้อเสนอแนะใด ๆ

ขอขอบคุณสำหรับเวลาของคุณ.

ตอบ

ปัญหานี้เกิดจากเธรดหลักที่ส่งคืนจากคำขอ POST ก่อนที่ไฟล์ CSV จะถูกเปิดโดยcsv_handler.get_reader(). ฉันยังไม่แน่ใจว่าไฟล์หายได้อย่างไรในขณะที่RequestHandlerมีCSVHandlerการอ้างอิงถึงrequestand fileวัตถุ บางทีมันอาจจะเป็นสิ่งที่ Django

ฉันแก้ไขโดยย้ายลอจิกของผู้อ่านไปที่คอนCSVHandlerสตรัคเตอร์และใช้ล็อคเพื่อป้องกันสภาพการแข่งขัน

class CSVHandler(object):
    def __init__(self, file):
        self.lock = threading.Lock()
        with self.lock:
            self.file = file
            data_set = self.file.read().decode('utf-8')
            io_string = io.StringIO(data_set)
            self.reader = csv.reader(io_string, delimiter=',', quotechar='"')

    def process_file(self, **kwargs):
        for row_data in self.reader:
            print('row_data:', row_data)