Skip to content

Commit 24dbaae

Browse files
committed
Merge conflict
2 parents c14f706 + 2f7a2c9 commit 24dbaae

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

docs/user-guide/running-offline.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# Running PyScript Offline
2+
3+
Althought users will want to create and share PyScript apps on the internet, there are cases when user want to run PyScript applications offline, in an airgapped fashion. This means that both PyScript core and the interpreter used to run code need to be served with the application itself. In short, the 2 main explicit tasks needed to create an offline PyScript application are:
4+
5+
* download and include PyScript core (`core.js`)
6+
* download and include the [Python] interpreters you want to use in your Application
7+
8+
## Downloading and Including PyScript's `core.js`
9+
10+
There are at least 2 ways to use PyScript offline:
11+
12+
* by **cloning the repository**, then building and installing dependencies and then run and then reach the `./dist/` folder
13+
* by **grabbing the npm package** which for simplicity sake will be the method used here at least until we find a better place to *pin* our *dist* folder via our CDN and make the procedure even easier than it is now
14+
15+
In the examples below, we'll assume we are creating a PyScript Application folder called `pyscript-offline` and we'll add all the necessary files to the folder.
16+
17+
First of all, we are going to create a `pyscript-offline` folder as reference.
18+
19+
```sh
20+
mkdir -p pyscript-offline
21+
cd pyscript-offline
22+
```
23+
24+
### Adding core by Cloning the Repository
25+
26+
You can build all the PyScript Core files by cloning the project repository and building them yourself. To do so, build the files by following the instructions in our [developer guide](/developers)
27+
28+
Once you've run the `build` command, copy the `build` folder that has been created into your `pyscript-offline` folder.
29+
30+
### Adding core by Installing `@pyscript/core` Locally
31+
32+
First of all, ensure you are in the folder you would like to test PyScirpt locally. In this case, the `pyscript-offline` folder we created earlier.
33+
34+
Once within the folder, be sure there is a `package.json` file. Even an empty one with just `{}` as content would work.
35+
This is needed to be sure the folder will include locally the `npm_modules` folder instead of placing the package in the parent folder, if any.
36+
37+
```sh
38+
# only if there is no package.json, create one
39+
echo '{}' > ./package.json
40+
41+
# install @pyscript/core
42+
npm i @pyscript/core
43+
```
44+
45+
At this point the folder should contain a `node_module` in it and we can actually copy its `dist` folder wherever we like.
46+
47+
```sh
48+
# create a public folder to serve locally
49+
mkdir -p public
50+
51+
# move @pyscript/core dist into such folder
52+
cp -R ./node_modules/@pyscript/core/dist ./public/pyscript
53+
```
54+
55+
## Setting up your application
56+
57+
Once you've added PyScript code following one of the methods above, that's almost it! We are half way through our goal but we can already create a `./public/index.html` file that loads the project:
58+
59+
```html
60+
<!DOCTYPE html>
61+
<html lang="en">
62+
<head>
63+
<meta charset="UTF-8">
64+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
65+
<title>PyScript Offline</title>
66+
<script type="module" src="/pyscript/core.js"></script>
67+
<link rel="stylesheet" href="/pyscript/core.css">
68+
</head>
69+
<body>
70+
<script type="mpy">
71+
from pyscript import document
72+
73+
document.body.append("Hello from PyScript")
74+
</script>
75+
</body>
76+
</html>
77+
```
78+
79+
To run this project directly, after being sure that `index.html` file is saved into the `public` folder, you can try:
80+
81+
```sh
82+
python3 -m http.server -d ./public/
83+
```
84+
85+
Alternatively, if you would like to test also `worker` features, you can try instead:
86+
87+
```sh
88+
npx static-handler --coi ./public/
89+
```
90+
## Downloading and Setting up a Local Interpreter
91+
92+
Good news! We are almost there. Now that we've:
93+
94+
* downloaded PyScript locally
95+
* created the skeleton of an initial PyScript App
96+
97+
we need to download and setup up an interpreter. PyScript officially supports *MicroPython* and *Pyodide* interpreters, so let's see how to do that for each one of them.
98+
99+
### Download MicroPython locally
100+
101+
Similarly to what we did for `@pyscript/core`, we can also install *MicroPython* from *npm*:
102+
103+
```sh
104+
npm i @micropython/micropython-webassembly-pyscript
105+
```
106+
107+
Our `node_modules` folder now should contain a `@micropython` one and from there we can move relevant files into our `public` folder, but let's be sure we have a target for that:
108+
109+
```sh
110+
# create a folder in our public space
111+
mkdir -p ./public/micropython
112+
113+
# copy related files into such folder
114+
cp ./node_modules/@micropython/micropython-webassembly-pyscript/micropython.* ./public/micropython/
115+
```
116+
117+
That folder should contain at least both `micropython.mjs` and `micropython.wasm` files and these are the files we are going to use locally via our dedicated config.
118+
119+
```html
120+
<!DOCTYPE html>
121+
<html lang="en">
122+
<head>
123+
<meta charset="UTF-8">
124+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
125+
<title>PyScript Offline</title>
126+
<script type="module" src="/pyscript/core.js"></script>
127+
<link rel="stylesheet" href="/pyscript/core.css">
128+
</head>
129+
<body>
130+
<mpy-config>
131+
interpreter = "/micropython/micropython.mjs"
132+
</mpy-config>
133+
<script type="mpy">
134+
from pyscript import document
135+
136+
document.body.append("Hello from PyScript")
137+
</script>
138+
</body>
139+
</html>
140+
```
141+
142+
### Install Pyodide locally
143+
144+
Currently there is a difference between MicroPython and Pyodide: the former does not have (*yet*) a package manager while the latest does, it's called *micropip*.
145+
146+
This is important to remember because while the procedure to have *pyodide* offline is very similar to the one we've just seen, if we want to use also 3rd party packages we also need to have these running locally ... but let's start simple:
147+
148+
```sh
149+
# install locally the pyodide module
150+
npm i pyodide
151+
152+
# create a folder in our public space
153+
mkdir -p ./public/pyodide
154+
155+
# move all necessary files into that folder
156+
cp ./node_modules/pyodide/pyodide* ./public/pyodide/
157+
cp ./node_modules/pyodide/python_stdlib.zip ./public/pyodide/
158+
```
159+
160+
Please **note** that also `pyodide-lock.json` file is needed so please don't change that `cp` operation as all `pyodide*` files need to be moved.
161+
162+
At this point, all we need to do is to change our *HTML* page to use *pyodide* instead:
163+
164+
```html
165+
<!DOCTYPE html>
166+
<html lang="en">
167+
<head>
168+
<meta charset="UTF-8">
169+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
170+
<title>PyScript Offline</title>
171+
<script type="module" src="/pyscript/core.js"></script>
172+
<link rel="stylesheet" href="/pyscript/core.css">
173+
</head>
174+
<body>
175+
<py-config>
176+
interpreter = "/pyodide/pyodide.mjs"
177+
</py-config>
178+
<script type="py">
179+
from pyscript import document
180+
181+
document.body.append("Hello from PyScript")
182+
</script>
183+
</body>
184+
</html>
185+
```
186+
187+
## Wrapping it up
188+
189+
We are basically done! If we try to disconnect from the internet but we still run our local server, the page will still show that very same *Hello from PyScript* message :partying_face:
190+
191+
We can now drop internet, still keeping the local server running, and everything should be fine :partying_face:
192+
193+
## Local Pyodide Packages
194+
195+
There's one last thing that users are probably going to need: the ability to install Python packages when using Pyodide.
196+
197+
In order to have also 3rd party packages available, we can use the bundle from [pyodide releases](https://github.com/pyodide/pyodide/releases/tag/0.24.1) that contains also packages.
198+
199+
Please note this bundle is more than 200MB: it not downloaded all at once, it contains each package that is required and it loads only related packages when needed.
200+
201+
Once downloaded and extracted, where in this case I am using `0.24.1` as reference bundle, we can literally copy and paste, or even move, all those files and folders inside the `pyodide-0.24.1/pyodide/*` directory into our `./public/pyodide/*` folder.
202+
203+
As the bundle contains files already present, feel free to either skip or replace the content, or even directly move that *pyodide* folder inside our `./public/` one.
204+
205+
Once it's done, we can now use any package we like that is available in *pyodide*. Let's see an example:
206+
207+
```html
208+
<!DOCTYPE html>
209+
<html lang="en">
210+
<head>
211+
<meta charset="UTF-8">
212+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
213+
<title>PyScript Offline</title>
214+
<script type="module" src="/pyscript/core.js"></script>
215+
<link rel="stylesheet" href="/pyscript/core.css">
216+
</head>
217+
<body>
218+
<py-config>
219+
interpreter = "/pyodide/pyodide.mjs"
220+
packages = ["pandas"]
221+
</py-config>
222+
<script type="py">
223+
import pandas as pd
224+
x = pd.Series([1,2,3,4,5,6,7,8,9,10])
225+
226+
from pyscript import document
227+
document.body.append(str([i**2 for i in x]))
228+
</script>
229+
</body>
230+
</html>
231+
```
232+
233+
If everything went fine, we should now be able to read `[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]` on the page *even* if we disconnect from the Internet.
234+
235+
And **that's all folks** :wave:

0 commit comments

Comments
 (0)