Runtimewarning enable tracemalloc to get the object allocation traceback как исправить

Работаю с PyQt5. Делаю приложение для логирования. Возникает проблема с потоком и asyncio.

При нажатии на кнопку должна запуститься асинхронная функция, которая получает через условия в постоянном цикле файлы на проверку и выводит полученные данные.

Асинхронная функция, которую я вызываю через поток:

async def deathcount():
    PLAYER_DEATH = '.*?Got character ZDOID from (w+) : 0:0'
    log = "c:/.../files/log.txt"
    while True:     
        with open(log, encoding='utf-8', mode='r') as f:
            f.seek(0,2)
            while True:
                line = f.readline()
                if(re.search(PLAYER_DEATH, line)):
                    pname = re.search(PLAYER_DEATH, line).group(1)
                    with open(file, 'a', newline='', encoding='utf-8') as dl:
                        ... ...
                        log(f"{gettime}{pname} умер!")
                await asyncio.sleep(0.2)

PLAYER_DEATH – переменная, хранящая в себе строчку с регулярным выражением.
В постоянном цикле проверяется log.txt, на наличие строки из PLAYER_DEATH.

При нажатии на кнопку должна сработать функция deathcount(), которая в итоге, при положительном ответе, должна вывести результат – log(f"{gettime}{pname} умер!")


Результат выводится с помощью потока, там же и вызываем функцию (deathcount()):
basic.py:

class QTextEditLogger(logging.Handler):

    def __init__(self, parent):
        super().__init__()

        self.PVELogs = QtWidgets.QPlainTextEdit(parent.centralwidget)
        self.PVELogs.setGeometry(QtCore.QRect(40, 50, 801, 491))
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.PVELogs.setFont(font)
        self.PVELogs.setStyleSheet("background-color: rgb(30, 30, 30); color: rgb(255, 255, 255);")
        self.PVELogs.setReadOnly(True)
        self.PVELogs.setPlainText("")
        self.PVELogs.setObjectName("PVELogs")

    def emit(self, record):
        msg = self.format(record)
        self.PVELogs.appendPlainText(msg)

class PVP(QtWidgets.QMainWindow, QWidget, MainInterface):
    def __init__(self):
        super().__init__()

        self.setupUi(self) #init gui

        # logging
        logTextBox = QTextEditLogger(self)
        #logTextBox.setFormatter(logging.Formatter(f'{gettime}%(message)s'))
        logging.getLogger().addHandler(logTextBox)
        logging.getLogger().setLevel(logging.DEBUG)

        root_logger= logging.getLogger()
        root_logger.setLevel(logging.DEBUG)
        handler = logging.FileHandler('PVPLog.log', 'w', 'utf-8') 
        handler.setFormatter(logging.Formatter('%(name)s, %(asctime)s, [%(levelname)s], %(message)s'))
        root_logger.addHandler(handler)

        self.PVELogs.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) 

        self.thread = WorkThread()
        self.thread.threadSignal.connect(self.func2)           
        self.onPVE.clicked.connect(self.func1)      

    def func1(self):
        self.thread.start()

    def func2(self, value):
        deathcount() # Вызываем функцию ! ! !

class WorkThread(QtCore.QThread):
    threadSignal = QtCore.pyqtSignal(int)

    def __init__(self):
        super().__init__()

    def run(self):     
        for i in range(10):
            self.msleep(200)
            self.threadSignal.emit(i)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mw = PVP()
    mw.show()

    sys.exit(app.exec())
    
loop = asyncio.new_event_loop()
loop.create_task(deathcount())
asyncio.set_event_loop(loop)

В конце файла создал новый цикл событий, советуясь данной темы


В конце асинхронной функции стоит ожидание (await asyncio.sleep(0.2)).
Но в итоге всё равно что-то не так.

c:......programmabasic.py:132: RuntimeWarning: coroutine 'deathcount' was never awaited
  deathcount()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Попробовал вызвать цикл в самой функции func2:

def func2(self, value):
    loop = asyncio.new_event_loop()
    loop.create_task(deathcount())
    asyncio.set_event_loop(loop)

Уже другой результат, так ещё в приложение появились интересные строчки:

C:UsersStepanAppDataLocalProgramsPythonPython39libasynciobase_events.py:667: RuntimeWarning: coroutine 'deathcount' was never awaited
  self._ready.clear()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

введите сюда описание изображения


Весь код

This article discusses the error ‘RuntimeWarning: Enable tracemalloc to get the object allocation traceback‘ in Python. If you are facing the same problem, check out the information below to find out the cause of this error and how to fix it by using the keyword ‘await‘. 

The cause of this error

First, we need to know that ‘asyncio‘ is a library for writing concurrent code using the async/await syntax. The sleep() method of this module is used to delay the currently executing task and allow another task to be executed.

Syntax:

asyncio.sleep(delay, result=None)

The reason why we received the error is that we forgot to use the “await” keyword before the sleep() method.

To illustrate, let me reproduce the error:

import asyncio

async def main():
    print('Loading…')
    
    asyncio.sleep(3)    
    print('Welcome to our site. We are LearnShareIT!')

asyncio.run(main())

Output:

RuntimeWarning: Enable tracemalloc to get the object allocation traceback

To fix this problem, you just need to add the keyword ‘await‘ before calling the sleep() method.

The ‘await‘ keyword is used as the signal to mark the breakpoint. It allows a coroutine to temporarily suspend execution and allow the program to return to it later.

Continuing with the example above, let’s see how we fix this problem:

import asyncio

async def main():
  
    print('Loading…')
    # Add the 'await' keyword in front of the asyncio.sleep() method
    await asyncio.sleep(3)
 
    print('Welcome to our site. We are LearnShareIT!')

asyncio.run(main())

Output:

At this point the error seems to have been solved with just a small change in the code. 

We set the block time to three seconds in the sleep() method. As you can see, the message ‘Loading…‘ appears first, then after ‘3‘ seconds message ‘Welcome to our site. We are LearnShareIT!‘ is printed.

Summary

To sum up, that’s all we want to talk about the error ‘RuntimeWarning: Enable tracemalloc to get the object allocation traceback‘ in Python. To solve this problem, you have to use the ‘await‘ keyword before calling the asyncio.sleep() method. Try it out in your project and see the results. Hopefully, the information we provide in this post will be helpful to you.

Maybe you are interested:

  • RuntimeError: dictionary changed size during iteration
  • Statements must be separated by newlines or semicolons

My name’s Christopher Gonzalez. I graduated from HUST two years ago, and my major is IT. So I’m here to assist you in learning programming languages. If you have any questions about Python, JavaScript, TypeScript, Node.js, React.js, let’s contact me. I will back you up.

Name of the university: HUST
Major: IT
Programming Languages: Python, JavaScript, TypeScript, Node.js, React.js

The RuntimeWarning: Enable tracemalloc to get the object allocation traceback warning occurs in Python when you write asyncio.sleep(1) expression without prepending the “await” keyword.

The easy fix for the RuntimeWarning: Enable tracemalloc to get the object allocation traceback is the asyncio.sleep(1) function you’re using in the main coroutine should await asyncio.sleep(1) instead of just asyncio.sleep(1).

The “await” keyword is used to make the call asynchronous and to wait for the result.

Python code that generates a warning

import asyncio

async def handle_event():
  print("Event handled!")

async def main():
  print("Starting event loop")
  asyncio.sleep(1)
  await handle_event()

asyncio.run(main())

Output

Starting event loop
/Users/Moe/Desktop/Code/pythonenv/app.py:8: RuntimeWarning: coroutine 'sleep' was never awaited
 asyncio.sleep(1)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Event handled!

You can see that we got the output but with the RuntimeWarning.

Correct Python code

import asyncio

async def handle_event():
  print("Event handled!")

async def main():
  print("Starting event loop")
  await asyncio.sleep(1)
  await handle_event()

asyncio.run(main())

Output

Starting event loop

Event handled!

The main coroutine runs until it encounters the await handle_event() line, at which point it yields control to the handle_event coroutine.

Once handle_event has finished processing the event, the control is returned to the main, and the event loop continues running until it is stopped.

tracemalloc in Python

To enable tracemalloc in an asyncio program, you can call tracemalloc.start function at the beginning of your program like this:

import tracemalloc

tracemalloc.start()

Once tracemalloc is enabled, you can use tracemalloc.get_traced_memory function to get the current traced memory usage, like this:

import tracemalloc

tracemalloc.start()

current, peak = tracemalloc.get_traced_memory()
print("Current memory usage is %d bytes; peak was %d bytes" % (current, peak))

Output

Current memory usage is 0 bytes; peak was 0 bytes

The tracemalloc can significantly impact your Python program’s performance, so it’s important to use it only when you need to debug memory usage issues.

That’s it.

Have you ever encountered a warning message in your Python code that reads “Runtime Warning: Enable tracemalloc to get the object allocation traceback”? If so, you’re not alone. This warning can be confusing for many Python developers, but it’s actually a helpful tool to use in your code.

What is tracemalloc?

Tracemalloc is a module in Python that allows you to trace memory usage in your code. It tracks memory allocation and deallocation of objects in your code. It also provides information about where the memory was allocated, the size of the allocation, and the traceback of the allocation.

Tracemalloc is particularly useful when you’re trying to diagnose memory leaks or performance issues in your code. By tracking memory allocation, you can see where object creation happens and what is using up the most memory. This information can help you identify the source of a memory leak or performance issue and allow you to make changes to your code to improve memory usage.

Enabling tracemalloc is easy. You simply need to import the tracemalloc module and call the tracemalloc.start() function. For example:

import tracemalloc
tracemalloc.start()

After calling tracemalloc.start(), tracemalloc will begin tracking memory allocation in your code. You can stop tracemalloc by calling tracemalloc.stop().

Getting the object allocation traceback

Once tracemalloc is enabled, you can use the tracemalloc.get_traced_memory() function to get information about memory usage in your code. This function returns a tuple with two values: the current size of allocated memory, and a list of traceback objects. Each traceback object contains information about an allocation, including the filename, line number, and function name of the allocation.

Here’s an example of how to use tracemalloc.get_traced_memory():

import tracemalloc

tracemalloc.start()

# Your code here

current, peak = tracemalloc.get_traced_memory()
print("Current memory usage is", current / 10**6, "MB")
print("Peak was", peak / 10**6, "MB")

traces = tracemalloc.get_traced_memory()[1]
for trace in traces[:3]:
    print("File:", trace.filename)
    print("Line:", trace.lineno)
    print("Function:", trace.name)
    print()

tracemalloc.stop()

In this example, we start tracemalloc and run our code. Then, we use tracemalloc.get_traced_memory() to get information about memory usage, including the current size of allocated memory and the peak memory usage. We then print out the filename, line number, and function name of the three largest allocations.

When do we encounter “Runtime Warning: Enable tracemalloc to get the object allocation traceback”

You will encounter the “Runtime Warning: Enable tracemalloc to get the object allocation traceback” message in Python when the interpreter is unable to track the memory allocation of an object, due to the absence of enabling of tracemalloc.

Tracemalloc is used to trace memory allocation in your Python code and provides information about where the memory was allocated, the size of the allocation, and the traceback of the allocation. When tracemalloc is not enabled, the interpreter can’t provide this information and generates the warning message.

Here’s an example of when you might encounter this warning:

import sys

x = [1, 2, 3, 4, 5]
print(sys.getobjects(0))

In this example, the sys.getobjects(0) function returns information about the memory allocation of all objects in the program. When you run this code, you’ll see the “Runtime Warning: Enable tracemalloc to get the object allocation traceback” message, indicating that tracemalloc is not enabled, and the memory allocation information is not available.

The warning message "Runtime Warning: Enable tracemalloc to get the object allocation traceback" is shown in this manner.

Runtime Warning: Enable tracemalloc to get the object allocation traceback

To avoid this warning, you need to enable tracemalloc before using sys.getobjects(0) or any other function that requires memory allocation information:

import sys
import tracemalloc

tracemalloc.start()

x = [1, 2, 3, 4, 5]
print(sys.getobjects(0))

tracemalloc.stop()

Output of the above code doesn't show any warning namely "Runtime Warning: Enable tracemalloc to get the object allocation traceback".

Output of the above code

In this example, by calling tracemalloc.start() before using sys.getobjects(0), we enable tracemalloc, and the memory allocation information is now available. The warning message is no longer generated, and we can successfully access the memory allocation information of all objects in the program.

“Runtime Warning: Enable tracemalloc to get the object allocation traceback” asyncio

The RuntimeWarning you’re encountering is related to tracemalloc, a built-in Python module for tracing memory usage in Python programs. The warning message is suggesting that you enable tracemalloc to get more information about the allocation of objects in your asyncio program.

Enabling tracemalloc will provide you with a traceback of the allocation of memory for the objects in your code. This can be useful for identifying memory leaks, understanding the performance of your code, and optimizing memory usage.

To enable tracemalloc, you can add the following line of code at the beginning of your program:

import tracemalloc
tracemalloc.start()

Once tracemalloc is enabled, you can use the tracemalloc.get_traced_memory() function to retrieve the current memory usage, and the tracemalloc.get_traced_allocators() function to get a list of all the objects that have been allocated since tracemalloc was started.

It’s important to note that enabling tracemalloc can affect the performance of your program, as it adds overhead to the memory allocation process. You should only enable tracemalloc when you need to debug memory usage, and turn it off when you’re done to avoid performance issues.

FAQs

What is the difference between tracemalloc and sys.getobjects?

Tracemalloc and sys.getobjects are two different methods of tracing memory allocation in Python. sys.getobjects is a deprecated method and has been replaced by tracemalloc.

Can I use tracemalloc in my production environment?

Yes, you can use tracemalloc in your production environment, but you should be careful when enabling it, as it can impact the performance of your code.

Conclusion

Tracemalloc is a powerful tool for understanding memory usage in Python. By tracking memory allocation and deallocation, tracemalloc can help you cure memory leaks and performance issues in your code. Enabling tracemalloc is easy, and once enabled, you can

get information about memory usage and the allocation traceback to help you identify and resolve memory-related problems.

It’s important to note that tracemalloc can have a performance impact on your code, as it adds overhead to memory allocation operations. However, this impact is usually very less, especially if you’re only using tracemalloc temporarily while debugging a specific issue.

Trending Python Articles

  • Efficiently Organize Your Data with Python Trie

    Efficiently Organize Your Data with Python Trie

    May 2, 2023

  • [Fixed] modulenotfounderror: no module named ‘_bz2

    [Fixed] modulenotfounderror: no module named ‘_bz2

    by Namrata GulatiMay 2, 2023

  • [Fixed] Cannot Set verify_mode to cert_none When check_hostname is Enabled

    [Fixed] Cannot Set verify_mode to cert_none When check_hostname is Enabled

    by Namrata GulatiMay 2, 2023

  • Prevent Errors with Python deque Empty Handling

    Prevent Errors with Python deque Empty Handling

    by Namrata GulatiMay 2, 2023

So I have a discord bot that has music commands in it. Today I added that if the bot doesn’t play anthing in 5 mins, it will leave the voice channel.

def search(arg):
    global last_played
    last_played = arg
    try:
        requests.get("".join(arg))
    except:
        arg = " ".join(arg)
    else:
        arg = "".join(arg)
    with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
        info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]

    return {'source': info['formats'][0]['url'], 'title': info['title']}


async def check_timer(ctx):
    global last_played
    guild = ctx.message.guild
    voice_client = guild.voice_client
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    music_check = last_played
    await asyncio.sleep(300)
    if not voice.is_playing() and music_check == last_played:
        await voice_client.disconnect()
        await ctx.send("No song is queued for 5 minutes. Left the voice channel!")


def play_next(ctx):
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    if len(song_queue) > 1:
        del song_queue[0]
        voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
        voice.is_playing()
    else:
        asyncio.create_task(check_timer(ctx))


@client.command()
async def play(ctx, *arg):
    channel = ctx.message.author.voice.channel

    if channel:
        voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
        song = search(arg)
        song_queue.append(song)

        if voice and voice.is_connected():
            await voice.move_to(channel)
        else:
            voice = await channel.connect()

        if not voice.is_playing():
            voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
            voice.is_playing()
        else:
            await ctx.send("Added to queue")
    else:
        await ctx.send("You're not connected to any channel!")

And the thing is when I run the bot. I get this error

2021-01-02T14:49:20.462802+00:00 app[worker.1]: Traceback (most recent call last):
2021-01-02T14:49:20.462823+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/discord/player.py", line 611, in _call_after
2021-01-02T14:49:20.462824+00:00 app[worker.1]:     self.after(error)
2021-01-02T14:49:20.462825+00:00 app[worker.1]:   File "/app/main.py", line 219, in <lambda>
2021-01-02T14:49:20.462834+00:00 app[worker.1]:     voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
2021-01-02T14:49:20.462837+00:00 app[worker.1]:   File "/app/main.py", line 201, in play_next
2021-01-02T14:49:20.462838+00:00 app[worker.1]:     asyncio.create_task(check_timer(ctx))
2021-01-02T14:49:20.462838+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/asyncio/tasks.py", line 360, in create_task
2021-01-02T14:49:20.462839+00:00 app[worker.1]:     loop = events.get_running_loop()
2021-01-02T14:49:20.462859+00:00 app[worker.1]: RuntimeError: no running event loop
2021-01-02T14:49:20.470913+00:00 app[worker.1]: /app/.heroku/python/lib/python3.9/site-packages/discord/player.py:615: RuntimeWarning: coroutine 'check_timer' was never awaited
2021-01-02T14:49:20.470914+00:00 app[worker.1]:   traceback.print_exception(type(exc), exc, exc.__traceback__)
2021-01-02T14:49:20.470915+00:00 app[worker.1]: RuntimeWarning: Enable tracemalloc to get the object allocation traceback

I searched up in the net and saw some people with the same error but their solution was to put await somewhere, I couldn’t see any place that needs an await.

PS I’m using heroku to host the bot.

Добавить комментарий