Skip to content

Commit

Permalink
Make module loading lazy (#162)
Browse files Browse the repository at this point in the history
* Make module loading lazy

* Catch less in JuliaModule.__getattr__

* Support star import

* Special handling for Main module

It adds an easier way to set variables in Julia's global namespace:

>>> from julia import Main
>>> Main.xs = [1, 2, 3]

* Deprecate Julia.__getattr__ (and make it lazy)

fixes #144

* Initialize Julia in JuliaModuleLoader if required

This makes `from julia import <Julia module>` works without the initial
setup.  Note that a custom setup can still be done by calling
`julia.Julia` with appropriate arguments *before* trying to import Julia
modules.

closes #39, #79

* More interfaces to JuliaMainModule

* Document the new API

* Properly remove prefix

* Fix JuliaModule.__all__; add .__dir__

* Cache original os.environ for tests

* Simplify JuliaModule.__try_getattr

* Add LegacyJulia to break infinite recursion

* Don't import in isamodule

Otherwise, trying to access undefined variables such as
`julia.Base.__path__` produces a warning from Julia before
`JuliaModule.__getattr__` raising `AttributeError`.

* Remove core._orig_env; it can be done in test code

* Use Enums as example sub-module

as Base.REPL was pulled out from Base in Julia 0.7.

* More import tests

* Remove noop code

* Fix wording
  • Loading branch information
tkf authored and stevengj committed Aug 1, 2018
1 parent 779808b commit e617ad9
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 104 deletions.
60 changes: 54 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,72 @@ If you run into problems using `pyjulia`, first check the version of `PyCall.jl`

Usage
-----
To call Julia functions from python, first import the library

`pyjulia` provides a high-level interface which assumes a "normal"
setup (e.g., `julia` is in your `PATH`) and a low-level interface
which can be used in a customized setup.

### High-level interface

To call a Julia function in a Julia module, import the Julia module
(say `Base`) with:

```python
from julia import Base
```

and then call Julia functions in `Base` from python, e.g.,

```python
import julia
Base.sind(90)
```

then create a Julia object that makes a bridge to the Julia interpreter (assuming that `julia` is in your `PATH`)
Other variants of Python import syntax also work:

```python
j = julia.Julia()
import julia.Base
from julia.Base import LinAlg # import a submodule
from julia.Base import sin # import a function from a module
```

You can then call Julia functions from python, e.g.
The global namespace of Julia's interpreter can be accessed via a
special module `julia.Main`:

```python
j.sind(90)
from julia import Main
```

You can set names in this module to send Python values to Julia:

```python
Main.xs = [1, 2, 3]
```

which allows it to be accessed directly from Julia code, e.g., it can
be evaluated at Julia side using Julia syntax:

```python
Main.eval("sin.(xs)")
```

### Low-level interface

If you need a custom setup for `pyjulia`, it must be done *before*
importing any Julia modules. For example, to use the Julia
interpreter at `PATH/TO/MY/CUSTOM/julia`, run:

```python
from julia import Julia
j = julia.Julia(jl_runtime_path="PATH/TO/MY/CUSTOM/julia")
```

You can then use, e.g.,

```python
from julia import Base
```


How it works
------------
PyJulia loads the `libjulia` library and executes the statements therein.
Expand Down
2 changes: 1 addition & 1 deletion julia/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .core import Julia, JuliaError
from .core import JuliaError, LegacyJulia as Julia
Loading

0 comments on commit e617ad9

Please sign in to comment.