2

Is there a way to run a .py file containing functions etc. from within the notebook such that the content of the .py file is treated as if it were directly in that cell?

For instance, say I have the file example.py in which a function test1 is defined that calls a function test4 which is defined in the ipython notebook. If I run example.py via %run examplye.py function test4 is unkown to test1. Can this be circumvented?

asked Jun 27, 2016 at 14:42

1 Answer 1

3

In Python2 the execfile function would do what you want. In Python 3 you have to emulate that by reading the contents of the file, compiling it and then making sure that it executes in the right namespace.

In a notebook cell I defined:

def f4(x):
 return x+x

I have a file testme.py containing the following code:

f4("something")

The following code cell appears to correctly execute the code in the file:

with open("testme.py") as f:
 code = compile(f.read(), "testme.py", 'exec')
 exec(code, globals(), locals())

It does indeed print "somethingsomething" as expected.

As mentioned in the comments, for debugging a changed module you can re-import it with reload() (Python2) or importlib.reload(). But the coupling of your code is rather tight - it's always going to be looking for the same function in the global namespace. This makes it very difficult to test, and it might be better to consider a dependency injection approach. Suppose your function looks as follows:

def my_func(a, b):
 ...
 f4(something)
 ...
 return result

This has to find the f4 function in its global namespace. A better-coupled solution would look like this:

def my_func(a, b, f):
 ...
 f(something)
 ...
 return result

You then call my_func with f4 as its third argument - you are in absolute control over the function that it calls, and can use other functions during testing should you want to instrument the code more carefully, and your code no longer requires the function to be in the global namespace of the calling module - you can pass it any function that you like.

answered Jun 27, 2016 at 14:52
Sign up to request clarification or add additional context in comments.

8 Comments

Hi, many thanks!! I will tried this now. Can I ask whether my question is a reasonable one in the sense that there is not a totally different way one would go about this issue, i.e. using pre-written code in ipython notebook? Thx, m
It's not a totally unreasonable way to proceed, but it has many dangers if the content is determined by the user - do you really want them executing any old lines of code in the context of your program?
Hi, thanks again. It did work. So I only use the code for myself. In my problem I have written some code in a notebook that I might want to use in a different notebook for a different problem later one. More concretely, I have data Y which is specific to the notebook, and function solve_model_X(Y) which I might also want to use for data Z in a different notebook. I believe I could work with a module, but this seems not conveniently either when solve_model_X is edited often, as is the case here. What do you think is the best way to do this? Thx
If your issue is that yo make frequent changes to the mosule in testing and you want to be able to reload it than consider using the reload function (Python 2) or importlib.reload (Python 3). This will replace the existing module with an updated version.
Of course there is nothing stopping you from passing the function as an argument - this is much better practice than making use of global function names.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.