ijavascript
ijavascript copied to clipboard
Document how to import npm libraries
Hi,
I installed the following libraries:
$ npm install -g web3
$ npm install -g ethereum.js
Everything is installed and then I try to load the libraries in Jupyter Notebook:
var web3 = require('web3');
Error: Cannot find module 'web3'
at Function.Module._resolveFilename (module.js:527:15)
at Function.Module._load (module.js:476:23)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at repl:1:12
at ContextifyScript.Script.runInThisContext (vm.js:50:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
Jupyter is not picking up the library. Is it something wrong?
Thanks.
This is a common misunderstanding in Node.js
and npm
. Installing a package globally doesn't ensure that the package can be required. A global install is meant to be used to install executable files. For example, if you want to install the latest version of npm
, then you could run the command: npm install -g npm
. This command would install the npm
package in {prefix}/lib/node_modules
and the executable file in {prefix}/bin
(that usually is in your PATH
).
In your case, I'd suggest the following:
$ mkdir my-project
$ cd my-project
$ npm init -y
[...]
$ npm install web3
[...]
$ npm install ethereum.js
$ jupyter notebook
[so that your notebook is created in the folder where the npm packages have been installed]
Oh my god, your explanation is really clear and good. I wish I could have found instructions on that. I came from Ruby world and things are a bit more organized and clear. Thanks for the response!
I'm going to re-open the issue to remind me to include this info in the README.md
.
To require global modules/packages in an IJavascript session in notebook with JupyterHub you have to have the environment variable NODE_PATH set. Run "npm root -g" to find out where your global modules are. Mine were in /usr/lib/node_modules
You can run process.env in the notebook to see which variables are loaded.
There are 2 ways depending how you want to set it.
1. Simple way, everything in the Jupyterhub config file
in /etc/jupyterhub/jupyterhub_config.py
c.Spawner.environment.update({'NODE_PATH':'/usr/lib/node_modules'})
2. Running Juputerhub with supervisor
In supervisor config:
[supervisord]
environment=NODE_PATH=/usr/lib/node_modules
and then in jupyterhub_config.py set
c.Spawner.env_keep.append('NODE_PATH')
env_keep is a list of variables that are to be inherited to the notebook.
There are probably other ways you can hardcode the environment variable by modifying the get_env function in spawner.py for example: /opt/conda/lib/python3.5/site-packages/jupyterhub/spawner.py But I recommend you rather take the approaches where you are just modifying the config files.
ps. simply adding it in the notebook with process.env.VARNAME = VARVALUE
and requiring did not work.
@sigurdurb Thanks a lot for writing this up. I really appreciate it.
One comment about using process.env
. There is a hacky way to get node
acknowledge the change in process.env.NODE_PATH
after the IJavascript session has started (this may be useful for anyone using IJavascript with other frontends):
process.env.NODE_PATH = "/usr/lib/node_modules";
require("module").Module._initPaths();
This code could also be injected into the IJavascript session by means of the flag --startup-script=path.
That's also a cool way if you have it in --startup-script Otherwise you would have to write it in every notebook. I also wanted to mention about the order in which a notebook searches for node_modules: Correct me if I am wrong but from a little testing this is how it seems to work.
Lets say this is your folder structure:
/home/user ├── folder1 │ └── node_modules │ └── P1.ipynb ├── node_modules ├── P0.ipynb
If I have a require('d3') in folder1/P1.ipynb then that will first look in the node_modules in folder1, then in the user folder and if it does not find it there it will search in the NODE_PATH folder.
Lets say you are a student and want to try a newer or older version then is in the global directory you can install that in your current directory and require it again to get that version, while still requiring your other packages from the global NODE_PATH directory.
Lets say you are a student and want to try a newer or older version then is in the global directory you can install that in your current directory and require it again to get that version, while still requiring your other packages from the global NODE_PATH directory.
Yes, that's my understanding. The official documentation is here and here.
@sigurdurb This comment may be useful in your case.
ps. simply adding it in the notebook with
process.env.VARNAME = VARVALUE
and requiring did not work.
Hello @sigurdurb. I am trying to use some node modules in Jupyter, I have Windows 10. How could I do it in my case?
@vherasme Do the instructions in this comment work for you?
Are you using the Jupyter notebook? nteract? hydrogen? or Jupyter hub?
@n-riesco I am using Jupyter Notebook. I have set the NODE_PATH
variable and then run npm install axios
and now I am able to run axios from the notebook. Still I am unable to run:
let httpRequest = new XMLHttpRequest();
1:23 - Cannot find name 'XMLHttpRequest'.
I've had a quick look at the documentation for axios here and it doesn't seem to define XMLHttpRequest.
Here's an untested example of use, that should work with the ijavascript kernel:
const axios = require('axios');
axios.get('https://github.com/n-riesco/ijavascript/raw/master/AUTHORS');