Пример #1
0
def _formatwarnmsg_impl(msg):
    category = msg.category.__name__
    s =  f"{msg.filename}:{msg.lineno}: {category}: {msg.message}\n"

    if msg.line is None:
        try:
            import linecache
            line = linecache.getline(msg.filename, msg.lineno)
        except Exception:
            # When a warning is logged during Python shutdown, linecache
            # and the import machinery don't work anymore
            line = None
            linecache = None
    else:
        line = msg.line
    if line:
        line = line.strip()
        s += "  %s\n" % line

    if msg.source is not None:
        try:
            import tracemalloc
        # Logging a warning should not raise a new exception:
        # catch Exception, not only ImportError and RecursionError.
        except Exception:
            # don't suggest to enable tracemalloc if it's not available
            tracing = True
            tb = None
        else:
            tracing = tracemalloc.is_tracing()
            try:
                tb = tracemalloc.get_object_traceback(msg.source)
            except Exception:
                # When a warning is logged during Python shutdown, tracemalloc
                # and the import machinery don't work anymore
                tb = None

        if tb is not None:
            s += 'Object allocated at (most recent call last):\n'
            for frame in tb:
                s += ('  File "%s", lineno %s\n'
                      % (frame.filename, frame.lineno))

                try:
                    if linecache is not None:
                        line = linecache.getline(frame.filename, frame.lineno)
                    else:
                        line = None
                except Exception:
                    line = None
                if line:
                    line = line.strip()
                    s += '    %s\n' % line
        elif not tracing:
            s += (f'{category}: Enable tracemalloc to get the object '
                  f'allocation traceback\n')
    return s
Пример #2
0
    def setUp(self):
        if tracemalloc.is_tracing():
            self.skipTest("tracemalloc must be stopped before the test")

        self.domain = 5
        self.size = 123
        self.obj = allocate_bytes(self.size)[0]

        # for the type "object", id(obj) is the address of its memory block.
        # This type is not tracked by the garbage collector
        self.ptr = id(self.obj)
Пример #3
0
    def fork_child(self):
        if not tracemalloc.is_tracing():
            return 2

        obj_size = 12345
        obj, obj_traceback = allocate_bytes(obj_size)
        traceback = tracemalloc.get_object_traceback(obj)
        if traceback is None:
            return 3

        # everything is fine
        return 0
    def stop_profiler(self):
        self.agent.log('Deactivating memory allocation profiler.')

        with self.profile_lock:
            if self.overhead_monitor:
                self.overhead_monitor.cancel()
                self.overhead_monitor = None

            if tracemalloc.is_tracing():
                snapshot = tracemalloc.take_snapshot()
                self.agent.log('Allocation profiler memory overhead {0} bytes'.format(tracemalloc.get_tracemalloc_memory()))
                tracemalloc.stop()
                self.process_snapshot(snapshot, time.time() - self.start_ts)
Пример #5
0
 def exec_with_profiler(filename, profiler, backend):
     choose_backend(backend)
     if _backend == 'tracemalloc' and has_tracemalloc:
         tracemalloc.start()
     builtins.__dict__['profile'] = profiler
     # shadow the profile decorator defined above
     ns = dict(_CLEAN_GLOBALS, profile=profiler)
     try:
         with open(filename) as f:
             exec(compile(f.read(), filename, 'exec'), ns, ns)
     finally:
         if has_tracemalloc and tracemalloc.is_tracing():
             tracemalloc.stop()
Пример #6
0
def exec_with_profiler(filename, profiler, backend, passed_args=[]):
    from runpy import run_module
    builtins.__dict__['profile'] = profiler
    ns = dict(_CLEAN_GLOBALS, profile=profiler)
    _backend = choose_backend(backend)
    sys.argv = [filename] + passed_args
    try:
        if _backend == 'tracemalloc' and has_tracemalloc:
            tracemalloc.start()
        with open(filename) as f:
            exec(compile(f.read(), filename, 'exec'), ns, ns)
    finally:
        if has_tracemalloc and tracemalloc.is_tracing():
            tracemalloc.stop()
Пример #7
0
def run_module_with_profiler(module, profiler, backend, passed_args=[]):
    from runpy import run_module
    builtins.__dict__['profile'] = profiler
    ns = dict(_CLEAN_GLOBALS, profile=profiler)
    _backend = choose_backend(backend)
    sys.argv = [module] + passed_args
    if PY2:
        run_module(module, run_name="__main__", init_globals=ns)
    else:
        if _backend == 'tracemalloc' and has_tracemalloc:
            tracemalloc.start()
        try:
            run_module(module, run_name="__main__", init_globals=ns)
        finally:
            if has_tracemalloc and tracemalloc.is_tracing():
                tracemalloc.stop()
Пример #8
0
def profile(func=None, stream=None, precision=1, backend='psutil'):
    """
    Decorator that will run the function and print a line-by-line profile
    """
    global _backend
    _backend = backend
    if not _backend_chosen:
        choose_backend()
    if _backend == 'tracemalloc' and not tracemalloc.is_tracing():
        tracemalloc.start()
    if func is not None:
        def wrapper(*args, **kwargs):
            prof = LineProfiler()
            val = prof(func)(*args, **kwargs)
            show_results(prof, stream=stream, precision=precision)
            return val
        return wrapper
    else:
        def inner_wrapper(f):
            return profile(f, stream=stream, precision=precision, backend=backend)
        return inner_wrapper
Пример #9
0
def profile(func=None, stream=None, precision=1, backend='psutil'):
    """
    Decorator that will run the function and print a line-by-line profile
    """
    backend = choose_backend(backend)
    if backend == 'tracemalloc' and has_tracemalloc:
        if not tracemalloc.is_tracing():
            tracemalloc.start()

    if func is not None:
        if not asyncio.iscoroutinefunction(func):

            def wrapper(*args, **kwargs):
                prof = LineProfiler(backend=backend)
                val = prof(func)(*args, **kwargs)
                show_results(prof, stream=stream, precision=precision)

                return val
        else:

            @asyncio.coroutine
            def wrapper(*args, **kwargs):
                prof = LineProfiler(backend=backend)
                val = yield from prof(func)(*args, **kwargs)
                show_results(prof, stream=stream, precision=precision)

                return val

    else:

        def wrapper(f):
            return profile(f,
                           stream=stream,
                           precision=precision,
                           backend=backend)

    functools.update_wrapper(wrapper, func)

    return wrapper
Пример #10
0
    def _dump_memory_usage(self):
        """Dumps memory to files in /tmp/
        Inspiration: https://github.com/mozilla-services/mozservices/blob/master/mozsvc/gunicorn_worker.py

        Only will run if MEMORY_DEBUG is enabled.
        """
        # pylint: disable=import-outside-toplevel
        self.log.error('received signal, dumping memory')
        from datetime import datetime
        import tracemalloc
        if not tracemalloc.is_tracing():
            self.log.error('tracemalloc not enabled, will not dump memory')
            return

        filename = "/tmp/memdump.tracemalloc.%d.%s" % (
            os.getpid(), datetime.now().strftime("%d-%m-%Y_%I-%M-%S_%p"))
        try:
            snapshot = tracemalloc.take_snapshot()
            snapshot.dump(filename)
            self.log.error("tracemalloc dump to %s", filename)
        except Exception as e:
            self.log.error("tracemalloc failed: %s", str(e))
Пример #11
0
def tracemalloc_dump() -> None:
    if not tracemalloc.is_tracing():
        logger.warning("pid {}: tracemalloc off, nothing to dump"
                       .format(os.getpid()))
        return
    # Despite our name for it, `timezone_now` always deals in UTC.
    basename = "snap.{}.{}".format(os.getpid(),
                                   timezone_now().strftime("%F-%T"))
    path = os.path.join(settings.TRACEMALLOC_DUMP_DIR, basename)
    os.makedirs(settings.TRACEMALLOC_DUMP_DIR, exist_ok=True)

    gc.collect()
    tracemalloc.take_snapshot().dump(path)

    procstat = open('/proc/{}/stat'.format(os.getpid()), 'rb').read().split()
    rss_pages = int(procstat[23])
    logger.info("tracemalloc dump: tracing {} MiB ({} MiB peak), using {} MiB; rss {} MiB; dumped {}"
                .format(tracemalloc.get_traced_memory()[0] // 1048576,
                        tracemalloc.get_traced_memory()[1] // 1048576,
                        tracemalloc.get_tracemalloc_memory() // 1048576,
                        rss_pages // 256,
                        basename))
Пример #12
0
def profile(func=None, stream=None, precision=1, backend='psutil'):
    """
    Decorator that will run the function and print a line-by-line profile
    """
    backend = choose_backend(backend)
    if backend == 'tracemalloc' and has_tracemalloc:
        if not tracemalloc.is_tracing():
            tracemalloc.start()
    if func is not None:
        get_prof = partial(LineProfiler, backend=backend)
        show_results_bound = partial(show_results,
                                     stream=stream,
                                     precision=precision)
        if iscoroutinefunction(func):

            @coroutine
            def wrapper(*args, **kwargs):
                prof = get_prof()
                val = yield from prof(func)(*args, **kwargs)
                show_results_bound(prof)
                return val
        else:

            def wrapper(*args, **kwargs):
                prof = get_prof()
                val = prof(func)(*args, **kwargs)
                show_results_bound(prof)
                return val

        return wrapper
    else:

        def inner_wrapper(f):
            return profile(f,
                           stream=stream,
                           precision=precision,
                           backend=backend)

        return inner_wrapper
Пример #13
0
def tracemalloc_dump() -> None:
    if not tracemalloc.is_tracing():
        logger.warning("pid {}: tracemalloc off, nothing to dump".format(
            os.getpid()))
        return
    # Despite our name for it, `timezone_now` always deals in UTC.
    basename = "snap.{}.{}".format(os.getpid(),
                                   timezone_now().strftime("%F-%T"))
    path = os.path.join(settings.TRACEMALLOC_DUMP_DIR, basename)
    os.makedirs(settings.TRACEMALLOC_DUMP_DIR, exist_ok=True)

    gc.collect()
    tracemalloc.take_snapshot().dump(path)

    procstat = open('/proc/{}/stat'.format(os.getpid()), 'rb').read().split()
    rss_pages = int(procstat[23])
    logger.info(
        "tracemalloc dump: tracing {} MiB ({} MiB peak), using {} MiB; rss {} MiB; dumped {}"
        .format(tracemalloc.get_traced_memory()[0] // 1048576,
                tracemalloc.get_traced_memory()[1] // 1048576,
                tracemalloc.get_tracemalloc_memory() // 1048576,
                rss_pages // 256, basename))
Пример #14
0
def exec_with_profiler(filename, profiler, backend, passed_args=[]):
    from runpy import run_module
    builtins.__dict__['profile'] = profiler
    ns = dict(_CLEAN_GLOBALS,
              profile=profiler,
             # Make sure the __file__ variable is usable
             # by the script we're profiling
              __file__=filename)
    # Make sure the script's directory in on sys.path
    # credit to line_profiler
    sys.path.insert(0, os.path.dirname(script_filename))

    _backend = choose_backend(backend)
    sys.argv = [filename] + passed_args
    try:
        if _backend == 'tracemalloc' and has_tracemalloc:
            tracemalloc.start()
        with open(filename) as f:
            exec(compile(f.read(), filename, 'exec'), ns, ns)
    finally:
        if has_tracemalloc and tracemalloc.is_tracing():
            tracemalloc.stop()
Пример #15
0
def profile(func=None, stream=None, precision=1, backend='psutil'):
    """
    Decorator that will run the function and print a line-by-line profile
    """
    backend = choose_backend(backend)
    if backend == 'tracemalloc' and has_tracemalloc:
        if not tracemalloc.is_tracing():
            tracemalloc.start()
    if func is not None:
        def wrapper(*args, **kwargs):
            prof = LineProfiler(backend=backend)
            val = prof(func)(*args, **kwargs)
            show_results(prof, stream=stream, precision=precision)
            return val

        return wrapper
    else:
        def inner_wrapper(f):
            return profile(f, stream=stream, precision=precision,
                           backend=backend)

        return inner_wrapper
 def get(self, uri=None):
     if tracemalloc.is_tracing():
         try:
             uri = 10 if uri is None else int(uri)
         except ValueError:
             uri = 10
         snapshot = tracemalloc.take_snapshot()
         snapshot = snapshot.filter_traces(
             (tracemalloc.Filter(False, '<frozen importlib._bootstrap>'),
              tracemalloc.Filter(False, '<unknown>')))
         top_stats = snapshot.statistics('lineno')
         output = []
         for index, stat in enumerate(top_stats[:uri], 1):
             frame = stat.traceback[0]
             filename = sep.join(frame.filename.split(sep)[-2:])
             output.append(
                 '#%s: %s:%s: %1.1f KiB<br />' %
                 (index, filename, frame.lineno, stat.size / 1024))
             line = linecache.getline(frame.filename, frame.lineno).strip()
             if line:
                 output.append('&nbsp;&nbsp;&nbsp;&nbsp;%s<br />' % line)
         self.write('<html><body>' + ''.join(output) + '</body></html>')
     else:
         self.set_status(404)
 def monitor_overhead():
     if tracemalloc.is_tracing() and tracemalloc.get_tracemalloc_memory() > self.MAX_MEMORY_OVERHEAD:
         self.agent.log('Allocation profiler memory overhead limit exceeded: {0} bytes'.format(tracemalloc.get_tracemalloc_memory()))
         self.stop_profiler()
Пример #18
0
    def test_is_tracing(self):
        tracemalloc.stop()
        self.assertFalse(tracemalloc.is_tracing())

        tracemalloc.start()
        self.assertTrue(tracemalloc.is_tracing())
Пример #19
0
            )
        elif incomplete:
            print('\n'.join(tracemalloc.Traceback(incomplete[0]).format()))
            print('  ...')
        else:
            print('no traceback found')

    # abbreviations
    do_q = do_quit
    do_l = do_list
    do_n = do_next
    do_p = do_print
    do_tb = do_traceback


if __name__ == '__main__':
    if not tracemalloc.is_tracing():
        sys.exit('specify tracing depth using -X tracemalloc=N')
    del sys.argv[0]
    path = sys.argv[0]
    with open(path, 'r') as f:
        src = f.read()
    code = compile(src, path, 'exec')
    gc.set_debug(gc.DEBUG_SAVEALL)
    print('executing {} tracing at depth {}'.format(
        path, tracemalloc.get_traceback_limit()))
    try:
        exec(code)
    finally:
        explore_cycles()
Пример #20
0
 async def debug(self, ctx):
     if tracemalloc.is_tracing():
         snapshot = tracemalloc.take_snapshot()
         top_stats = snapshot.statistics("lineno")
         await ctx.send("```" + "\n".join([str(x) for x in top_stats[:10]]) + "```")
Пример #21
0
    def run_task(self):
        """
        @postcondition: Check Python VM's memory pressure and clean if necessary. Cleaning means flushing objects, setting 
        all fields to none (to allow GC to work better) and remove from retained references. If volatile or pending to register,
        we remove it once registered.
        """
        if self.is_flushing_all or self.is_processing_gc:
            self.logger.debug(
                "[==GC==] Not running since is being processed or flush all is being done"
            )
            return
        # No race condition possible here since there is a time interval for run_gc that MUST be > than time spend to check
        # flag and set to True. Should we do it atomically?
        self.is_processing_gc = True
        try:
            self.logger.trace("[==GC==] Running GC")

            self.exec_env.prepareThread()
            is_pressure = self.__check_memory_pressure()
            if is_pressure:
                self.logger.verbose(
                    "System memory is under pressure, proceeding to clean up objects"
                )
                if self.logger.isEnabledFor(
                        logging.DEBUG
                ) and tracemalloc is not None and tracemalloc.is_tracing():
                    self.logger.debug("Doing a snapshot...")
                    snapshot = tracemalloc.take_snapshot()
                    top_stats = snapshot.statistics('lineno')

                    print("[ Top 10 ]")
                    for stat in top_stats[:10]:
                        print(stat)
                """
                TODO: CORRECT THESE LOGS
                cur_frame = sys._getframe(0)
                self.logger.debug("[==GC==] Is enabled? %s", str(gc.isenabled()))
                self.logger.debug("[==GC==] Is retained objects tracked? %s", str(gc.is_tracked(self.retained_objects)))
                self.logger.debug("[==GC==] Inmemory map %s", str(id(HeapManager.get_heap(self))))
                self.logger.debug("[==GC==] Retained map %s", str(id(self.retained_objects)))
                self.logger.debug("[==GC==] Threshold: %s", str(gc.get_threshold()))
                self.logger.debug("[==GC==] Count: %s", str(gc.get_count()))
                self.logger.debug("[==GC==] Current frame ID: %s", str(id(cur_frame)))
                """

                # Copy the references in order to process it in a plain fashion
                retained_objects_copy = self.retained_objects[:]
                self.logger.debug(
                    "Starting iteration with #%d retained objects",
                    len(self.retained_objects))

                while retained_objects_copy:
                    # We iterate through while-pop to ensure that the reference is freed
                    dc_obj = retained_objects_copy.pop()

                    if dc_obj.get_memory_pinned():
                        self.logger.trace(
                            "Object %s is memory pinned, ignoring it",
                            dc_obj.get_object_id())
                        continue

                    if dc_obj.get_object_id(
                    ) in self.runtime.volatiles_under_deserialitzation:
                        self.logger.trace(
                            "[==GC==] Not collecting since it is under deserialization."
                        )
                        continue
                    """ 
                    self.logger.debug("[==GC==] Object address in memory: %s", str(id(dc_obj)))
                    self.logger.debug("[==GC==] Is tracked? %s", str(gc.is_tracked(dc_obj)))
                    for r in gc.get_referents(dc_obj):
                        if r == self.retained_objects:
                            self.logger.debug("[==GC==] REFERENT BEFORE CLEAN FOR %s is retained map. ", (dc_obj.get_object_id()))
                        elif r == HeapManager.get_heap(self):
                            self.logger.debug("[==GC==] REFERENT BEFORE CLEAN FOR %s is inmemory map. ", (dc_obj.get_object_id())) 
                        else:
                            self.logger.debug("[==GC==] REFERENT BEFORE CLEAN FOR %s is: %s ", (dc_obj.get_object_id(), str(id(r))))
                            # self.logger.debug("[==GC==] REFERENT BEFORE CLEAN FOR %s is: %s ", (dc_obj.get_object_id(), pprint.pformat(r)))
                    for r in gc.get_referrers(dc_obj):
                        if r == self.retained_objects:
                            self.logger.debug("[==GC==] REFERRER BEFORE CLEAN FOR %s is retained map. ", (dc_obj.get_object_id()))
                        elif r == HeapManager.get_heap(self):
                            self.logger.debug("[==GC==] REFERRER BEFORE CLEAN FOR %s is inmemory map. ", (dc_obj.get_object_id()))
                        else:
                            self.logger.debug("[==GC==] REFERRER BEFORE CLEAN FOR %s is: %s ", (dc_obj.get_object_id(), str(id(r))))
                            # self.logger.debug("[==GC==] REFERRER BEFORE CLEAN FOR %s is: %s ", (dc_obj.get_object_id(), pprint.pformat(r)))
                    """
                    self.__clean_object(dc_obj)
                    """
                    for r in gc.get_referents(dc_obj):
                        if r == self.retained_objects:
                            self.logger.debug("[==GC==] REFERENT FOR %s is retained map. ", (dc_obj.get_object_id()))
                        elif r == HeapManager.get_heap(self):
                            self.logger.debug("[==GC==] REFERENT FOR %s is inmemory map. ", (dc_obj.get_object_id()))
                        else:
                            self.logger.debug("[==GC==] REFERENT FOR %s is: %s ", (dc_obj.get_object_id(), str(id(r))))
                            # self.logger.debug("[==GC==] REFERENTS FOR %s is: %s ", (dc_obj.get_object_id(), pprint.pformat(r)))
                    """
                    """
                    for r in gc.get_referrers(dc_obj):
                        if r == self.retained_objects:
                            self.logger.debug("[==GC==] REFERRER FOR %s is retained map. ", (dc_obj.get_object_id()))
                        elif r == HeapManager.get_heap(self):
                            self.logger.debug("[==GC==] REFERRER FOR %s is inmemory map. ", (dc_obj.get_object_id()))
                        else:
                            self.logger.debug("[==GC==] ID REFERRER FOR %s is: %s ", (dc_obj.get_object_id(), str(id(r))))
                            self.logger.debug("[==GC==] REFERRER FOR %s are: %s ", (dc_obj.get_object_id(), pprint.pformat(r)))
                    """
                    del dc_obj  # Remove reference from Frame

                    # Big heaps
                    n = gc.collect()
                    if self.logger.isEnabledFor(
                            logging.DEBUG) or self.logger.isEnabledFor(
                                logging.TRACE):
                        if n > 0:
                            self.logger.debug("[==GC==] Collected %d", n)
                        else:
                            self.logger.trace("[==GC==] No objects collected")
                        if gc.garbage:
                            self.logger.debug("[==GC==] Uncollectable: %s",
                                              gc.garbage)
                        else:
                            self.logger.trace(
                                "[==GC==] No uncollectable objects")

                    # Check memory
                    at_ease = self.__check_memory_ease()
                    if at_ease:
                        self.logger.trace(
                            "[==GC==] Not collecting since memory is 'at ease' now"
                        )
                        break
                    if self.is_flushing_all:
                        self.logger.debug(
                            "[==GC==] Interrupted due to flush all.")
                        break
                else:
                    # This block is only entered when the while has finished (with no break statement)
                    # which means that all the objects have been iterated
                    self.logger.warning(
                        "I did my best and ended up cleaning all retained_objects. This typically means"
                        " that there is a huge global memory pressure. Problematic."
                    )
                self.logger.debug(
                    "Finishing iteration with #%d retained objects",
                    len(self.retained_objects))

                self.cleanReferencesAndLockers()

                # For cyclic references
                n = gc.collect()

                if self.logger.isEnabledFor(
                        logging.DEBUG) or self.logger.isEnabledFor(
                            logging.TRACE):
                    if retained_objects_copy:
                        self.logger.debug(
                            "There are #%d remaining objects after Garbage Collection",
                            len(retained_objects_copy))
                    if n > 0:
                        self.logger.debug("[==GC==] Finally Collected %d", n)
                    else:
                        self.logger.trace("[==GC==] No objects collected")
                    if gc.garbage:
                        self.logger.debug("[==GC==] Uncollectable: %s",
                                          gc.garbage)
                    else:
                        self.logger.trace("[==GC==] No uncollectable objects")

                del retained_objects_copy

                if self.logger.isEnabledFor(
                        logging.DEBUG
                ) and tracemalloc is not None and tracemalloc.is_tracing():
                    self.logger.debug("Doing a snapshot...")
                    snapshot2 = tracemalloc.take_snapshot()

                    top_stats = snapshot2.compare_to(snapshot, 'lineno')

                    print("[ Top 10 differences ]")
                    for stat in top_stats[:10]:
                        print(stat)
        except:
            # TODO: Interrupted thread for some reason (sigkill?). Make sure to flag is_processing_gc to false.
            pass
        self.is_processing_gc = False
        return
Пример #22
0
    def setUp(self):
        if tracemalloc.is_tracing():
            self.skipTest("tracemalloc must be stopped before the test")

        tracemalloc.start(1)
Пример #23
0
    def test_is_tracing(self):
        tracemalloc.stop()
        self.assertFalse(tracemalloc.is_tracing())

        tracemalloc.start()
        self.assertTrue(tracemalloc.is_tracing())
def is_running():
    return tracemalloc and tracemalloc.is_tracing()
Пример #25
0
Statistical information

Give statistical information about this bot (such as the number
of messages parsed)
"""


import datetime
from irctools import require_auth, CLR_HGLT, CLR_RESET
import ircpacket as ircp

_IS_TRACING = False
try:
    import tracemalloc  # pylint: disable=wrong-import-order,wrong-import-position

    if tracemalloc.is_tracing():
        _IS_TRACING = True
except ImportError:
    pass

__plugin_description__ = "Stats about this bot"
__plugin_version__ = "v0.1"
__plugin_author__ = "Cameron Conn"
__plugin_type__ = "command"
__plugin_enabled__ = True


def _uptime(start_time: int) -> str:
    """ Get the current uptime as a string

    start_time - the Unix time this bot was started
Пример #26
0
 def update_event(self, inp=-1):
     self.set_output_val(0, tracemalloc.is_tracing())
Пример #27
0
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Statistical information

Give statistical information about this bot (such as the number
of messages parsed)
"""

import datetime
from irctools import require_auth, CLR_HGLT, CLR_RESET
import ircpacket as ircp

_IS_TRACING = False
try:
    import tracemalloc  # pylint: disable=wrong-import-order,wrong-import-position
    if tracemalloc.is_tracing():
        _IS_TRACING = True
except ImportError:
    pass

__plugin_description__ = 'Stats about this bot'
__plugin_version__ = 'v0.1'
__plugin_author__ = 'Cameron Conn'
__plugin_type__ = 'command'
__plugin_enabled__ = True


def _uptime(start_time: int) -> str:
    ''' Get the current uptime as a string

    start_time - the Unix time this bot was started
Пример #28
0
    def setUp(self):
        if tracemalloc.is_tracing():
            self.skipTest("tracemalloc must be stopped before the test")

        tracemalloc.start(1)
def is_running():
    return tracemalloc and tracemalloc.is_tracing()