# I successfully ran an Elm worker from Python

**URL:** <https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451>\
**Category:** Show and Tell\
**Created:** [April 6, 2020, 4:56am UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451 "2020-04-06T04:56:46Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 6, 2020, 4:56am UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/1 "2020-04-06T04:56:47Z")

</div>

For the past hour or so I have been working on a Python module that can run a compiled Elm 0.19 module that runs on `Platform.worker`. It’s actually very easy to do and it uses less than 40 lines of Python code. I’m using this [dukpy](https://github.com/kovidgoyal/dukpy) library to run the javascript (it’s not available on PyPI and there is a completely different package with the same name on PyPI).

This is the Python code:

```auto
import dukpy
import time

GLOBALS = '''
var console = {
	warn: function(str) {},
	log: function(str) {},
};
'''

def set_timeout(f, milliseconds):
	time.sleep(milliseconds)
	f()

class Elm:

	def __init__ (self, jscode, main_module, flags=''):
		self.ctx = dukpy.Context()
		self.ctx.eval(GLOBALS)
		self.ctx.g.setTimeout = set_timeout

		self.ctx.eval(jscode)
		self.ctx.eval(f'var elm = Elm.{main_module}.init({flags});')

	def subscribe(self, port_name):
		def decor(f):
			self.ctx.g.tempfunc = f
			self.ctx.eval(f'elm.ports.{port_name}.subscribe(tempfunc);')
			return f

		return decor

	def send(self, port_name, arg='null'):
		self.ctx.eval(f'elm.ports.{port_name}.send({arg});')

```

As an example, I wrote a counter app that runs on `Platform.worker`. It defines these ports:

```elm
port getNum : ( () -> msg ) -> Sub msg -- Immediately triggers gotNum
port increment : ( () -> msg ) -> Sub msg
port decrement : ( () -> msg ) -> Sub msg

port gotNum : Int -> Cmd msg -- Sends the current counter state to JavaScript

```

And this is how I run this from Python (after running `elm make --output=counter.js`):

```auto
with open('counter.js', 'r') as f:
	elm = Elm(f.read(), 'Main')

@elm.subscribe('gotNum')
def when_num_received(num):
	print(f'Got current number: {num}')

elm.send('getNum')
elm.send('increment')
elm.send('getNum')
elm.send('increment')
elm.send('increment')
elm.send('getNum')
elm.send('decrement')
elm.send('getNum')

```

Output:

```auto
Got current number: 0
Got current number: 1
Got current number: 3
Got current number: 2

```

---

<div class="post-metadata">

**Author:** ![Viir](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/viir/32/4103_2.png) [@Viir](https://discourse.elm-lang.org/u/Viir)\
**Post date:** [April 6, 2020, 5:46am UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/2 "2020-04-06T05:46:40Z")

</div>

> [@DullBananas](#):
>
> var console = { warn: function(str) {}, log: function(str) {}, };

Nice solution to fix the dependencies on `console`! It looks like this is simpler than trying to remove the dependencies in the javascript.

---

<div class="post-metadata">

**Author:** ![francescortiz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/francescortiz/32/1721_2.png) [@francescortiz](https://discourse.elm-lang.org/u/francescortiz)\
**Post date:** [April 6, 2020, 6:53am UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/3 "2020-04-06T06:53:44Z")

</div>

Python’s mojo: “If it quacks like it’s a duck”. It makes sense that a pythonish solution comes from a python developer 😉

> **[Duck typing](https://en.wikipedia.org/wiki/Duck_typing)**
>
> Duck typing in computer programming is an application of the duck test—"If it walks like a duck and it quacks like a duck, then it must be a duck"—to determine if an object can be used for a particular purpose. With normal typing, suitability is determined by an object's type. In duck typing, an object's suitability is determined by the presence of certain methods and properties, rather than the type of the object itself. 
> This is a simple example in Python 3 that demonstrates how any object may...

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 6, 2020, 4:03pm UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/4 "2020-04-06T16:03:17Z")

</div>

Maybe I could use this to create a framework for making command line applications with Elm

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [April 6, 2020, 5:20pm UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/5 "2020-04-06T17:20:15Z")

</div>

Probably the easiest way of doing this is with NodeJS - a little bit of JS wrapper code around an Elm program. You can also publish them to npm this way, which gives you a way of publishing command line tools that web developers are already familiar with.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 6, 2020, 5:49pm UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/6 "2020-04-06T17:49:18Z")

</div>

or maybe this could be used to use elm as a way to extend your aoplication

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [April 6, 2020, 8:49pm UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/7 "2020-04-06T20:49:50Z")

</div>

Yes, if you had an existing Python application and wanted to render some HTML from it, server side, it could be a useful way of doing that and getting the data more directly from the Python part into the Elm part. An alternative way might be to add a REST API to the Python bit and then build a UI in Elm on top of that.

I have an equivalent project for Elm in Java (not updated for 0.19 though). Was doing server side Elm rendering with it:

> **[rupertlssmith/elm-java](https://github.com/rupertlssmith/elm-java)**
>
> Server side rendering with static Elm programs running in a JVM - rupertlssmith/elm-java

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [April 21, 2020, 10:56pm UTC](https://discourse.elm-lang.org/t/i-successfully-ran-an-elm-worker-from-python/5451/9 "2020-04-21T22:56:43Z")

</div>

Closed on April 21, 2020, 10:56pm UTC

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
