lpy icon indicating copy to clipboard operation
lpy copied to clipboard

Didn't output timeit results

Open et2010 opened this issue 6 years ago • 1 comments

2e doesn't output timing results

Take following code snippet for example:

import timeit
timeit.timeit(
    "obj.method()", """
class SomeClass:
    def method(self):
        pass
obj= SomeClass()
""")

It should output:

#=> 0.21603588491238312

However, the number was not showing.

et2010 avatar Nov 02 '18 08:11 et2010

lpy relies on the built-in python-mode to do the eval.

Here's what python-mode does. Step 1: it creates a file e.g. /tmp/pyanEMgi with contents:

timeit.timeit(
    "obj.method", """
class SomeClass:
    def method(self):
        pass
obj = SomeClass()
    """)

Step 2: it evaluates this code in the REPL:

import codecs, os
__code = codecs.open('/tmp/pyanEMgi', encoding='utf-8').read().encode('utf-8')
exec(compile(__code, '/tmp/pyanEMgi', 'exec'))

You can verify that this code actually produces no output.

The solution is to patch the built-in function by adding print(_):

(defun python-shell--save-temp-file (string)
  (let* ((temporary-file-directory
          (if (file-remote-p default-directory)
              (concat (file-remote-p default-directory) "/tmp")
            temporary-file-directory))
         (temp-file-name (make-temp-file "py"))
         (coding-system-for-write (python-info-encoding)))
    (with-temp-file temp-file-name
      (insert string)
      (insert "\nprint(_)\n")
      (delete-trailing-whitespace))
    temp-file-name))

Please test if it works for you. The problem with this is that it prints the last value, so if after evaluating a value like 2+2 you then evaluate class Foo:..., it will echo "4", since defining a class produces no value.

I think the best workaround is probably to rewrite your code like this:

print(timeit.timeit(
    "obj.method", """
class SomeClass:
    def method(self):
        pass
obj = SomeClass()
    """))

abo-abo avatar Dec 19 '18 20:12 abo-abo