This happens in interactive mode because when you create a new flow or task with the same name as an existing flow or task, Prefect tries to load the file where the redefinition happened so it can give you a friendly warning message. But, of course, that doesn't work if your code isn't in a file 🙂
Normally, you wouldn't need to redefine an existing task because there's usually a better way to accomplish your goals. But if you just want to do a few quick experiments in an interactive session, I can see why redefining and re-running tasks would be handy.
A quick way to work around this would be giving the tasks different names so Prefect doesn't see the redefinition as a duplicate. In that case, your sample would look like:
@task(name="1")
def my_task():
print("hello")
@task(name="2")
def my_task():
print("hello")
# Prefect remains happy
If you want to get really creative, you could run something like this at the beginning of your interactive Python session:
import uuid
from prefect import task as _task
task = lambda fn, **kwargs: _task(fn, name=str(uuid.uuid4()), **kwargs)
# then, these should work
@task
def my_task():
print("hello")
@task
def my_task():
print("hello")
# Prefect still happy
Disclaimer: you should definitely
not do anything like that in production code. But if you just want a quick way to redefine a task a couple of dozen times when you're experimenting in a Python REPL, it should be okay.