Giter Club home page Giter Club logo

reloadr's Introduction

Reloadr

Python hot code reloading tool.

pip install reloadr

Usage

You can simply decorate your functions / classes with @autoreload and you are ready to go.

from reloadr import autoreload

@autoreload
def do_something(a, b):
    return a + b

@autoreload
class SomeThing:
    def do_stuff(self):
        pass

Advanced usage

To reload the code manually, you can use of the following:

from reloadr import reloadr

@reloadr
class SomeThing:
    def do_stuff(self):
        pass

# Manual reload
SomeThing._reload()

# Automatic reload using filesystem notifications
SomeThing._start_watch_reload()

# Automatic reload in a thread every 1 second
SomeThing._start_timer_reload(1)

Examples

Launch an example (they each contain an infinite loop), then change the source code of the decorated class or function.

git clone https://github.com/hoh/reloadr.git

python examples/01_manual_reload.py

How it works

Instead of importing your source file again, which can lead to undesired side effects, Reloadr fetches the new code of your function within the Python source file, and executes that code in the environment of your already loaded module.

This allows it to reload code that is followed by blocking instructions such as the infinite loops you can find in the examples.

To achieve this, Reloadr relies on RedBaron , an great tool for manipulating Python source code.

Future plans

This project is still in its early stages. All ideas for improvement are welcome.

reloadr's People

Contributors

hoh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reloadr's Issues

Reloading from Jupyter Notebooks is not supported

Seeing as this is a super early stage project, I assume you just haven't got to this yet and this exception will demonstrate the issue. I was trying to use reloadr on a class I defined in a JupyterNotebook.


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-ba3cff0dfb1e> in <module>()
----> 1 TDAmeritradeScraper._reload()

/usr/local/lib/python3.6/site-packages/reloadr.py in _reload(self)
    116         "Manually reload the class with its new code."
    117         try:
--> 118             self._target = reload_class(self._target)
    119             # Replace the class reference of all instances with the new class
    120             for ref in self._instances:

/usr/local/lib/python3.6/site-packages/reloadr.py in reload_class(target)
     56 def reload_class(target):
     57     "Get the new class object corresponding to the target class."
---> 58     return reload_target(target, 'class')
     59 
     60 

/usr/local/lib/python3.6/site-packages/reloadr.py in reload_target(target, kind, filepath)
     43     assert kind in ('class', 'def')
     44 
---> 45     source = get_new_source(target, kind, filepath)
     46     module = inspect.getmodule(target)
     47     # We will populate these locals using exec()

/usr/local/lib/python3.6/site-packages/reloadr.py in get_new_source(target, kind, filepath)
     28     assert kind in ('class', 'def')
     29 
---> 30     filepath = filepath or inspect.getsourcefile(target)
     31     red = redbaron.RedBaron(open(filepath).read())
     32     # dumps() returns Python code as a string

/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/inspect.py in getsourcefile(object)
    652     Return None if no way can be identified to get the source.
    653     """
--> 654     filename = getfile(object)
    655     all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:]
    656     all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:]

/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/inspect.py in getfile(object)
    622             if hasattr(object, '__file__'):
    623                 return object.__file__
--> 624         raise TypeError('{!r} is a built-in class'.format(object))
    625     if ismethod(object):
    626         object = object.__func__

TypeError: <module '__main__'> is a built-in class

Auto reloads are incompatible with gevent

It seems reloadr doesnt work with gevent patching? Is this a known limitation? Is there possibly a workaround?

from reloadr import reloadr
from gevent import monkey

monkey.patch_all()

@reloadr
class Foo:
    pass

Foo._start_watch_reload()  # hangs forever
print("this is never executed")

I'm running python 3.7.7, reloadr 0.4.1 and gevent 20.9.0

Edit: manual reloads (Foo._reload()) seem to work!

Trigger reloader from somewhere else.

I'd like a way of triggering the reloader from somewhere else, and when the code isn't necessarily in a file.

In Shoebot we execute code once per frame that may be in a .
New code can arrive from an external editor, which we crudely swap out.

It would be good if if we could use reloadr and call something to tell it that the new code has been updated and what it is.

We have a crude rollback system too - if the code raises and exception or has a syntax error, we roll back to the last known good code and state.
Not sure if that's in the scope of reloadr, but would be good, we use that so that the user can edit code as it's drawing animations etc.

Parent classes cannot be reloaded

Hello, I encounter the following error "TypeError: init() takes 2 positional arguments but 4 were given" whenever I import the classes in a package I'm coding.
I get the previous error whenever I define a Child class, which inherits form a decorated Parent Class using autoreload, regardless if the Child class is decorated or not.
In reality I would like to decorate both classes since in my project I'd be heavily adjusting both.
I was wondering if this is simply not possible, if it is a mistake on my part, or if its a fixable error?

I'm currently using reloadr-0.4.1 and python 3.8.2

Here is a simple example that reproduces the behavior.

from reloadr import autoreload
@autoreload
class Example_Parent():
    def __init__(self, *args, **kwargs):
        self.example_parent = "example parent"

class Example_Child(Example_Parent):
    def __init__(self, *args, **kwargs):
        super().__init__
        self.example_child = "example child"

reload function which is inside another function

Environment : Linux os
Hi am trying to reload the function which is present within another function like this:

async def run():
    print("RUN Component")
    @reloadr
     async def function2():
          print("Function 2")
          return 0
      while True:
          await function2()
          sleep(5)

and calling that in while loop.
The problem here is when i change the print statement in function2 and save it am getting the following error and the value printing is still the old one.

**Error**
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/home/pop/.local/lib/python3.6/site-packages/watchdog/observers/api.py", line 199, in run
    self.dispatch_events(self.event_queue, self.timeout)
  File "/home/pop/.local/lib/python3.6/site-packages/watchdog/observers/api.py", line 368, in dispatch_events
    handler.dispatch(event)
  File "/home/pop/.local/lib/python3.6/site-packages/watchdog/events.py", line 330, in dispatch
    _method_map[event_type](event)
  File "/home/pop/.local/lib/python3.6/site-packages/reloadr.py", line 89, in on_modified
    this._reload()
  File "/home/pop/.local/lib/python3.6/site-packages/reloadr.py", line 146, in _reload
    self._target = reload_function(self._target, self._filepath)
  File "/home/pop/.local/lib/python3.6/site-packages/reloadr.py", line 63, in reload_function
    return reload_target(target, 'def', filepath)
  File "/home/pop/.local/lib/python3.6/site-packages/reloadr.py", line 50, in reload_target
    exec(source, module.__dict__, locals_)
  File "<string>", line 2
    def function2():
    ^
IndentationError: unexpected indent

Errors with simple script

When using the following script:

from reloadr import autoreload
import time

@autoreload
def foo():
    return 4

if __name__ == "__main__":
    print("Here we go")
    while True:
        print(foo())
        time.sleep(1)

I get this error when I edit and save the foo function:

Exception in thread Thread-40:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/site-packages/watchdog/observers/api.py", line 199, in run
    self.dispatch_events(self.event_queue, self.timeout)
  File "/usr/lib/python3.6/site-packages/watchdog/observers/api.py", line 368, in dispatch_events
    handler.dispatch(event)
  File "/usr/lib/python3.6/site-packages/watchdog/events.py", line 330, in dispatch
    _method_map[event_type](event)
  File "/usr/lib/python3.6/site-packages/reloadr.py", line 89, in on_modified
    this._reload()
  File "/usr/lib/python3.6/site-packages/reloadr.py", line 146, in _reload
    self._target = reload_function(self._target, self._filepath)
  File "/usr/lib/python3.6/site-packages/reloadr.py", line 63, in reload_function
    return reload_target(target, 'def', filepath)
  File "/usr/lib/python3.6/site-packages/reloadr.py", line 45, in reload_target
    source = get_new_source(target, kind, filepath)
  File "/usr/lib/python3.6/site-packages/reloadr.py", line 31, in get_new_source
    red = redbaron.RedBaron(open(filepath).read())
FileNotFoundError: [Errno 2] No such file or directory: '<string>'

I am executing this as python3 reloadtest.py.

error with reloading a subclass

When using the following script:

import time
from reloadr import reloadr
class C:

    def __init__(self, name):
        print 'base C : ' + name


@reloadr
class Car(C):

    def __init__(self, name):
        super(Car, self).__init__(name)
        self.name = name
    def position(self):
        return self.name, 8

if __name__ == "__main__":

    print("Here we go")
    car = Car('t1')
    while True:
        print(car.position())
        time.sleep(1)
        Car._reload()

got this error when run the script:

 Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_umd.py", line 198, in runfile
     pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
   File " reload_test.py", line 21, in <module>
    car = Car('t1')
  File "reloadr.py", line 108, in __call__
    instance = self._target.__call__(*args, **kwargs)
AttributeError: class Car has no attribute '__call__'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.