PyPy.js: Python in the web browser
pypyjs.org
pypyjs.org
https://github.com/replit-archive/empythoned
I deployed this at scale at Codecademy were millions of users were using it to learn Python but hit a lot of problems with it. For one, if you're in a 3rd world country then the bundle size is a non-starter (this is potentially solved with WASM being a binary format). Even if you managed to download the bundle lots of old computers would run out of memory trying to parse the JS (again probably solved by the binary AST format of WASM). Because of this and a few other issues (the dev experience of emscripten was really hard) we had to move away to running code on remote containers.
Now that I'm back working on Repl.it full time I'm excited to play again with the tech and see what we can do with it this time around.
Welcome to PyPy.js!
>>> import os
>>> os.listdir('/')
['tmp', 'home', 'dev', 'lib']
>>> f = open('/what', 'w')
>>> f.write('hey')
>>> f.close()
>>> os.listdir('/')
['tmp', 'home', 'dev', 'lib', 'what']
>>> open('/what').read()
'hey'
What is in the stack that makes that work? >>> import os
>>> for root, dirs, files in os.walk('/'):
... for d in dirs:
... print os.path.join(root, d) + '/'
... for f in files:
... print os.path.join(root, f)
...
/tmp/
/home/
/dev/
/lib/
/home/web_user/
/dev/shm/
/dev/null
/dev/tty
/dev/tty1
/dev/random
/dev/urandom
/dev/stdin
/dev/stdout
/dev/stderr
/dev/shm/tmp/
/lib/pypyjs/
/lib/pypyjs/lib_pypy/
/lib/pypyjs/lib-python/
/lib/pypyjs/lib_pypy/encodings/
/lib/pypyjs/lib_pypy/UserDict.py
/lib/pypyjs/lib_pypy/__future__.py
/lib/pypyjs/lib_pypy/_abcoll.py
/lib/pypyjs/lib_pypy/_structseq.py
/lib/pypyjs/lib_pypy/_weakrefset.py
/lib/pypyjs/lib_pypy/abc.py
/lib/pypyjs/lib_pypy/base64.py
/lib/pypyjs/lib_pypy/code.py
/lib/pypyjs/lib_pypy/codecs.py
/lib/pypyjs/lib_pypy/codeop.py
/lib/pypyjs/lib_pypy/copy.py
/lib/pypyjs/lib_pypy/copy_reg.py
/lib/pypyjs/lib_pypy/genericpath.py
/lib/pypyjs/lib_pypy/getopt.py
/lib/pypyjs/lib_pypy/linecache.py
/lib/pypyjs/lib_pypy/os.py
/lib/pypyjs/lib_pypy/posixpath.py
/lib/pypyjs/lib_pypy/pwd.py
/lib/pypyjs/lib_pypy/re.py
/lib/pypyjs/lib_pypy/repr.py
/lib/pypyjs/lib_pypy/sre_compile.py
/lib/pypyjs/lib_pypy/sre_constants.py
/lib/pypyjs/lib_pypy/sre_parse.py
/lib/pypyjs/lib_pypy/stat.py
/lib/pypyjs/lib_pypy/struct.py
/lib/pypyjs/lib_pypy/traceback.py
/lib/pypyjs/lib_pypy/types.py
/lib/pypyjs/lib_pypy/warnings.py
/lib/pypyjs/lib_pypy/weakref.py
/lib/pypyjs/lib_pypy/encodings/__init__.py
/lib/pypyjs/lib_pypy/encodings/aliases.py
/lib/pypyjs/lib_pypy/encodings/ascii.py
/lib/pypyjs/lib_pypy/encodings/base64_codec.py
/lib/pypyjs/lib_pypy/encodings/hex_codec.py
/lib/pypyjs/lib_pypy/encodings/latin_1.py
/lib/pypyjs/lib_pypy/encodings/raw_unicode_escape.py
/lib/pypyjs/lib_pypy/encodings/string_escape.py
/lib/pypyjs/lib_pypy/encodings/unicode_escape.py
/lib/pypyjs/lib_pypy/encodings/unicode_internal.py
/lib/pypyjs/lib_pypy/encodings/utf_16.py
/lib/pypyjs/lib_pypy/encodings/utf_8.py
/lib/pypyjs/lib-python/2.7/My code basically calls int(time.time()) until its value changes, doing i+=1 for every time it did not change (n=10 for every platform (python2/3/pypy/browser)). My browser is Firefox 61, full code here: https://hastebin.com/turenofise.py
But you made me think: indeed, the underlying call could be slower from JS whereas from pypy/python{2,3} it's fast (or vice versa). So I just tested a version where it checks how long ten million iterations take (n=3). Code here: https://hastebin.com/uyuhecabek.py
browser/pypy 5.25 seconds
python 3.6.6 2.16 seconds
python 3.7.0 2.08 seconds
python 2.7.15 1.42 seconds
pypy 6.0.0 0.01 seconds
Since there is no syscall to be made, pypy can do this in compiled code and is blazingly fast (I bet C/assembly isn't much faster there), and the rest seems comparable to the previous estimate: the browser version is 2.25× slower compared to python3 (now 2.43×) and 3.33× slower compared to python2 (now 3.70×).Edit: SO answer explaining the PyPy JIT: https://stackoverflow.com/questions/37377787/what-kind-of-ji...
Iteration 0 took -0.9660000801086426s
Iteration 1 took -0.9519999027252197s
Iteration 2 took -0.9499998092651367s
It is about 10 times slower with Chrome on my computer. Iteration 0 took 0.6579999923706055s
Iteration 1 took 0.6540000438690186s
Iteration 2 took 0.6460001468658447s
(I noticed the code from hastebin was an old version, I forgot to swap the starttime-time.time() in the version I posted. Not that it matters much, just change the sign.)Running it on OP's website again just to be sure, it now takes 4.9 seconds instead of 5.25, so there is some variance there, but this is still a big difference. This is Firefox as well (see another comment in this subthread), I don't have Chromium installed.
Besides, if calculations are important, you would use numpy.
Here's the code:
import time
a=-1
j = 0
i=0
while j < 10:
if a!=int(time.time()):
print(i)
a = int(time.time())
i=0
j += 1
i += 1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
It is used by a class taught on Coursera (Introduction to Interactive Programming in Python)
From what I can see:
- PyPy.js benefit: runs faster
- codeskulptor benefit: can use GUI components
To my surprise it was faster than Jupyter / CPython for some tasks (e.g. loading and parsing large CSVs).
I'd expect a much larger difference in tasks that are pure Python (loading a CSV is done primarily through the csv module, i.e. all the hot loops are in C).
I'd expect some overhead from sandboxing etc., but it should be fairly close to native speed.
Naturally, I changed the first code block to this:
from random import randint, seed
seed()
"\n".join([randint(5, 25) * ' ' + s for s in ['such code', 'much live', 'wow']])Something like (client-side):
thread::send $::tcl-web::server -async {
do stuff
} placeToStoreResult
...
vwait placeToStoreResult
do stuff with result $placeToStoreResultHowever the language I yearn for in browsers is Lua.
> Specifically, 2.7 will receive bugfix support until January 1, 2020. All 2.7 development work will cease in 2020.
> I've updated the PEP to say 2.7 is completely dead on Jan 1 2020. The final release may not literally be on January 1st, but we certainly don't want to support 2.7 through all of 2020.
https://www.python.org/dev/peps/pep-0373/#maintenance-releas... https://mail.python.org/pipermail/python-dev/2018-March/1523...
I have no idea why would a project of this caliber would start by using Python 2 instead of Python 3.
Edit: When I started reading about GCF, all docs said I could only use Python 2. Later I found that they seem to be on the way to change this. But still, I was very surprised that Python 2 was even an option to begin with.
import antigravity Welcome to PyPy.js!
>>> from __future__ import braces
File "<console>", line 1
SyntaxError: not a chance
>>>Also, wouldn't this be better implemented with WASM?
So pretty much like every Python project then. What's happening to the Python community?
If you've been writing JavaScript your whole career you might not know what that looks like.
A lot of the low-hanging fruit for generally-useful libraries have already been created, and have reached maturity?
Micropython is pretty recent, and pretty impressive.
It's moved from "growing" to "well established." I don't see many people lamenting something is in CPAN and not pip anymore. It shouldn't be surprising that you find more stale projects and packages as time goes on. Most of the interesting stuff is in the development with specific packages (Pandas, Salt, OpenStack, etc.).
What I gather is that it's compiling CPython to WASM and ships it along with some other utilities. It looks pretty cool.
>>> os.getlogin()
'root'
Nice joke :) File "<console>", line 2
return f'{fname} {surname} is {age}.'
^
SyntaxError: invalid syntaxSo this is a subset of Python or something like that?
Edit: Just checked the site and see it uses PyPy which states -- on their site -- the python version is 3.5.3
a, *b = range(3)
which should be 3.5 i think.
For all other cases, stay in Node or use a lib from a language more suited to WASM compilation. Now, if it's an option between this and a native Node module, that depends on your opinion of Node FFI and native Node modules.
A) Run it as a subprocess
B) Call it over HTTP request/response
C) Use a message broker like AMQP
hello
>>>import json
>>>
Dope, everything I need.
everything that can be written in JS will be written in JS!!Why, exactly, does this have such a garbage-ancient version of Python?
import os
for subdir, dirs, files in os.walk('./'):
for file in files:
print file
os.remove(file)
Perhaps the environment is "fake", and these files don't really exist, even in some sandbox... otherwise, seems like this might pose a security risk.There is no way that pypy.js is able to access local files on your machine outside of the browser sandbox.
2. uh ok I'll paste it into an editor and remove the added indentation and then copy&paste that to test it
3. ... ok. I'll look at the code and reformat every single line and copy&paste that
the oldest complaint abides
import os
os.listdir('/')
The answer, by the way, is no.That's not malicious code... it removes files from a sandbox... you can refresh the page and see for yourself.
> And if you're so clever to post that code
There's no need to be rude... there's an honest question and lack of understanding in my post - educate me, don't talk down to me.
> why don't you try similar code to see if it really has access to your files
The question was if someone could break out of a sandbox, such as with Java Applets and Adobe Flash. I have no idea how to do that - I'm not a security specialist, nor some sort of hacker guy.
> The answer, by the way, is no.
From the sandbox and using the standard `import os`, ya, you're right. The question, again, is what if someone got outside the sandbox?
This is different from the examples you mention: there is no external software that creates the sandbox (whereas with Java and Flash you had to install those as plugins). It's really just Javascript as it is built into the browser. Any vulnerability in this "sandbox" is a vulnerability in the browser, not some 3rd party plugin.
Put differently, this pypy emulation is no different from the Javascript API that was in your browser already. This isn't a new plugin, just using Javascript to emulate Python through the Pypy interpreter.