Python“模块”对象没有属性“ _strptime”

时间:2019-07-19 19:18:03

标签: python multithreading datetime

这个错误已经出现了很长一段时间,但是我不希望它频繁出现,这是我压缩它的时候了。

我看到,只要我有多个线程,它就会出现。应用程序相当广泛,因此我将在下面发布代码片段。

我正在使用datetime.datetime strptime将消息格式化为datetime对象。当我在多线程函数中使用此函数时,该错误出现在一个线程上,而在另一个线程上运行得很好。

错误

Exception in thread Thread-7:
Traceback (most recent call last):
  File "C:\Users\kdarling\AppData\Local\Continuum\anaconda3\envs\lobsandbox\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\kdarling\AppData\Local\Continuum\anaconda3\envs\lobsandbox\lib\threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "d:\kdarling_lob\gryphon_eagle\proj_0012_s2_lobcorr\main\lobx\src\correlator\handlers\inputhandler.py", line 175, in _read_socket
    parsed_submit_time = datetime.datetime.strptime(message['msg']['submit_time'], '%Y-%m-%dT%H:%M:%S.%fZ')
AttributeError: 'module' object has no attribute '_strptime'

好的,这有点奇怪,因为它在第一个线程上被调用,但是第二个线程通过使用datetime.datetime可以完全正常工作。

想法

  • 我要覆盖什么吗?毕竟是Python。 ,我不在任何地方使用日期时间。
  • 我正在通过ABC使用继承,那么父级呢? 不,,此错误早已发生,并且我不会覆盖父级中的任何内容。

我的下一个想法是“ 这是带有Datetime模块的Python魔术吗?”,因此我决定使用 time.strptime

错误

Exception in thread Thread-6:
Traceback (most recent call last):
  File "C:\Users\kdarling\AppData\Local\Continuum\anaconda3\envs\lobsandbox\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Users\kdarling\AppData\Local\Continuum\anaconda3\envs\lobsandbox\lib\threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "d:\kdarling_lob\gryphon_eagle\proj_0012_s2_lobcorr\main\lobx\src\correlator\handlers\inputhandler.py", line 176, in _read_socket
    parsed_submit_time = time.strptime(message['msg']['submit_time'], '%Y-%m-%dT%H:%M:%S.%fZ')
AttributeError: 'module' object has no attribute '_strptime_time'

代码

import datetime
import heapq
import json
import os
import socket
import sys
import time

from io import BytesIO
from threading import Thread

from handler import Handler


class InputStreamHandler(Handler):

    def __init__(self, configuration, input_message_heap):
        """
        Initialization function for InputStreamHandler.
        :param configuration: Configuration object that stores specific information.
        :type configuration: Configuration
        :param input_message_heap: Message heap that consumers thread will populate.
        :type input_message_heap: Heap
        """
        super(InputStreamHandler, self).__init__()
        self.release_size = configuration.get_release_size()
        self.input_src = configuration.get_input_source()
        self.input_message_heap = input_message_heap
        self.root_path = os.path.join(configuration.get_root_log_directory(), 'input', 'sensor_data')
        self.logging = configuration.get_logger()
        self.Status = configuration.Status

        self.get_input_status_fn = configuration.get_input_functioning_status
        self.update_input_status = configuration.set_input_functioning_status

        if configuration.get_input_state() == self.Status.ONLINE:
            self._input_stream = Thread(target=self._spinup_sockets)
        elif configuration.get_input_state() == self.Status.OFFLINE:
            self._input_stream = Thread(target=self._read_files)

    def start(self):
        """
        Starts the input stream thread to begin consuming data from the sensors connected.
        :return: True if thread hasn't been started, else False on multiple start fail.
        """
        try: 
            self.update_input_status(self.Status.ONLINE)
            self._input_stream.start()
            self.logging.info('Successfully started Input Handler.')
        except RuntimeError:
            return False
        return True

    def status(self):
        """
        Displays the status of the thread, useful for offline reporting.
        """
        return self.get_input_status_fn()

    def stop(self):
        """
        Stops the input stream thread by ending the looping process.
        """
        if self.get_input_status_fn() == self.Status.ONLINE:
            self.logging.info('Closing Input Handler execution thread.')
            self.update_input_status(self.Status.OFFLINE)
            self._input_stream.join()

    def _read_files(self):
        pass

    def _spinup_sockets(self):
        """
        Enacts sockets onto their own thread to collect messages.
        Ensures that blocking doesn't occur on the main thread.
        """
        active_threads = {}
        while self.get_input_status_fn() == self.Status.ONLINE:
            # Check if any are online
            if all([value['state'] == self.Status.OFFLINE for value in self.input_src.values()]):
                self.update_input_status(self.Status.OFFLINE)
                for active_thread in active_threads.values():
                    active_thread.join()
                break

            for key in self.input_src.keys():
                # Check if key exists, if not, spin up call
                if (key not in active_threads  or not active_threads[key].isAlive()) and self.input_src[key]['state'] == self.Status.ONLINE:
                    active_threads[key] = Thread(target=self._read_socket, args=(key, active_threads,))
                    active_threads[key].start()
        print(self.input_src)

    def _read_socket(self, key, cache):
        """
        Reads data from a socket, places message into the queue, and pop the key.
        :param key: Key corresponding to socket.
        :type key: UUID String
        :param cache: Key cache that corresponds the key and various others.
        :type cache: Dictionary
        """
        message = None
        try:
            sensor_socket = self.input_src[key]['sensor']

        ...

            message = json.loads(stream.getvalue().decode('utf-8'))
            if 'submit_time' in message['msg'].keys():
        # Inherited function
                self.write_to_log_file(self.root_path + key, message, self.release_size)
                message['key'] = key
                parsed_submit_time = time.strptime(message['msg']['submit_time'], '%Y-%m-%dT%H:%M:%S.%fZ')
                heapq.heappush(self.input_message_heap, (parsed_submit_time, message))
            cache.pop(key)
        except:
        pass

其他思想

  • 没有引发此错误时,两个线程共享一个称为 write_to_log_file 的通用功能。有时,当write_to_log_file检查操作系统是否具有特定目录时,即使该目录在那里,它也会返回False,从而发生错误。使用Python并同时访问相同的功能(即使对于外部模块)是否可以解决问题?该错误也从未如此一致。

总体而言,仅运行单个线程/连接时不会发生此错误。

0 个答案:

没有答案