About Rick van Hattem (Wolph)


My name is Rick van Hattem (nickname: Wolph, hence the domain name). For the last couple of years I have been working on a couple of startups, more recently I have decided to take a step back and do some consultancy to do research for my next startup.

My main areas of expertise are currently:

  • Scaling systems with large amounts of data and/or users
  • PostgreSQL
  • Python
  • Django

Mastering Python, the Python 3.5 and above book I wrote for experienced Python programmers to improve their skills:

For more info about me and my projects:

The things that interest me are mainly the big/difficult problems, the more difficult a problem is the more fun I’ll have solving it.

Bookmark and Share

40 Responses to “About Rick van Hattem (Wolph)”

  1. Anshu Kumar | 2016-07-18 at 08:42:01 #

    Hi Rick,

    I was going through your wonderful book, mastering python.

    I think when you are explaing “Beautiful is better than ugly” in Chapter-2

    filter_modulo = lambda i, m: [i[j] for i in range(len(i))
    if i[j] % m]

    It looks like a nit, for loop should iterated with variable “j”.

    Thank You,

    • Rick van Hattem | 2016-07-18 at 09:07:23 #

      Hi Anshu,

      You are indeed correct. While rewriting that code sample (I switched from i and j to items and modulo) it seems I have forgotten to modify that sample as well.

      The sample should be either:
      [python]filter_modulo = lambda i, m: [i[j] for j in range(len(i)) if i[j] % m][/python]

      filter_modulo = lambda items, modulo: [items[i] for i in range(len(items))
      if items[i] % modulo]

      Thanks for letting me know. I’ve added the correct code samples to the repository: https://github.com/mastering-python/code/commit/f7ec4fc2480614ea8369f7d27a99b22046e2a780

      Best, Rick

  2. Mark London | 2017-02-25 at 02:58:48 #

    Can your “Django Tags Input” module be used in front end user forms in django, rather than the admin page? K.s

  3. Tom Deg. | 2017-05-05 at 22:13:48 #

    Hi Rick

    First, many thanks for your numpy-stl module. Most helpful. I have one suggestion to make:

    The only rotation you have enabled in your code is around an arbitrary axis (and a point), which is super helpful. I understand that you are using the rotation_matrix function which calculates the appropriate rotation matrix, which you then use to rotate the stl.

    I would find it very useful (and powerful) to provide a second function that would allow a rotation around a user supplied rotation matrix.

    What I am thinking is this:

    rollMatrix = mesh.Mesh.rotation_matrix((1,0,0), heel_rads)
    pitchMatrix = mesh.Mesh.rotation_matrix((0,1,0), pitch_rads)
    combinedMatrix = numpy.dot(rollMatrix, pitchMatrix)

    This would allow for very easy chaining of matrices.

    The work-around is very easy, but this seems like a really quick and useful addition…

    Kind regards,


  4. Bob | 2018-01-10 at 15:48:03 #


    Just wanted to say thanks for python-progress bar, it’s very nice

  5. Pinchas Weisberg | 2018-01-30 at 10:13:40 #

    I am trying to use portalocker in order to lock a file written to by a few processes:

    with open(timing_filename, ‘a’, 1) as timing_file:
    portalocker.lock(timing_file, portalocker.LOCK_EX)

    However, some lines are skipped, it seems the locking is NON blocking or there is a short timeout.

    Thank you, in advance, for any help you can give me.

    • Rick van Hattem | 2018-01-30 at 13:13:54 #

      The problem is (most likely) that you are opening the file in append mode before locking it, which means that your position within the file is decided before the file is locked. If someone writes something in the mean time your script won’t notice that.

      To resolve this you can simply seek to the end after locking: timing_file.seek(0, os.SEEK_END)

  6. Grov | 2018-11-05 at 14:40:29 #


    Since when have you been using my wolf avatar?


    • Rick van Hattem | 2018-11-05 at 15:30:39 #

      I’ve downloaded it about 15 years ago from a website that had free to use animated gifs. Did you make it at some point?

  7. Grov | 2018-11-08 at 16:41:58 #

    It was made for me as a gif about 16 years ago and i have been using it ever since. Xan you remember which website you got it from?

  8. Isaac | 2018-11-10 at 18:03:30 #

    It is exactly the same

  9. Johan van der Veen | 2019-01-27 at 11:14:01 #

    Hi Rick,

    Is there any SW update available for the RT68U router with the Mesh functionality?
    I have a Mesh configuration but still see a lack of transmission power.
    My current Router software version is

    I hope you can help me just a little

    • Rick van Hattem | 2019-01-28 at 10:24:22 #

      I think your best bet is to change your location to one that allows for a lot of transmit power. Beyond that the new firmwares are limited in terms of transmit power

  10. Jörn Jaenecke | 2019-06-18 at 19:35:43 #

    Hi Rick,

    in the list of authors of “PostgreSQL Server Programming – Second Edition” you are named as main contributor to the pl/Python part.
    Under “Debugging pl/Python” (p.288) is recommended to import the plpy module into my regular Python development environement to ease debugging: “Just put the module in your path and do import plpy before you try running yourprospective PL/PythonU functions in an ordinary interpreter”

    My problem: I do not find any plpy module or site-package neither within my postgresql-installation nor searching the internet.
    Please can you give me a hint how to use plpy from outside psql?
    thank you


  11. Abelardo | 2019-07-09 at 04:08:54 #

    Hello Rick,

    I have a need to convert a series of really large ASCII .stl files to binary format to reduce their size and hopefully improve the importing of them into a CAD software. I run into your code and have successfully install it via conda. I am having a bit of difficulty understanding how to exactly run the functions right at the top of your documentation where it says ‘Initial usage’, then you list three functions. For instance, say i want to execute the first one:
    stl2bin your_ascii_stl_file.stl new_binary_stl_file.stl

    How exactly can i execute this one? I am doing the following first:
    1) import numpy
    2) import stl
    3) ????


    • Rick van Hattem | 2019-07-09 at 04:16:29 #

      It’s actually far easier than that, the stl2bin script is automatically added to the bin or scripts directory upon install. On windows that means the scripts directory of your current python environment. On other systems its the bin directory.

      Running the code directly is also possibly tough, you can find it here: https://github.com/WoLpH/numpy-stl/blob/develop/stl/main.py#L78

      • Abelardo | 2019-07-09 at 04:44:54 #

        Thanks Rick. Your first suggestion helped!

        When i execute the command,i get the following errors:

        RuntimeError: (True, “Incorrect value b’facet normal'”)

        During handling of the above exception, another exception occurred:

        AssertionError: File too large, got 1814065765 triangles which exceeds the maximum of 100000000

        I should say all my ASCII .stl files have facets with normals set to 0.0, 0.0, 0.0. Most CAD packages can handle this. Also, my .stl file have a really large number of facets, i’d say 2 to 3 orders of magnitude larger than what is set on MAX_COUNT.

        How can i resolve this?

        • Rick van Hattem | 2019-07-09 at 12:34:20 #

          Having that many facets often indicates trying to read a binary file as ascii but it’s easy enough to override:
          from stl import stl
          # Or whatever large value, the default is 1e8
          # https://github.com/WoLpH/numpy-stl/blob/develop/stl/stl.py#L45
          stl.MAX_COUNT = 1e12

          The errors appear to indicate that you’re reading the file as binary instead of ascii though. I would suggest forcing ascii:
          from stl import stl

          stl_file = stl.StlMesh(

          • Abelardo Garza | 2019-07-09 at 19:50:59 #

            Hi Rick,

            Thanks for your help, i truly appreciate your time. I went ahead and tried what you suggested but still got the facet normal error. Please see below.



            In [1]: import numpy

            In [2]: import stl

            In [3]: from stl import stl

            In [4]: stl.MAX_COUNT = 1e15

            In [5]: stl_file = stl.StlMesh(mode=stl.Mode.ASCII,filename=’Salt_initial.stl’,calculate_normals=False,remove_empty_are
            …: as=False,)
            RuntimeError Traceback (most recent call last)
            —-> 1 stl_file = stl.StlMesh(mode=stl.Mode.ASCII,filename=’Salt_initial.stl’,calculate_normals=False,remove_empty_areas=False,)

            D:\Apps\anaconda2\lib\site-packages\stl\stl.py in from_file(cls, filename, calculate_normals, fh, mode, speedups, **kwargs)
            321 with open(filename, ‘rb’) as fh:
            322 name, data = cls.load(
            –> 323 fh, mode=mode, speedups=speedups)
            325 return cls(data, calculate_normals, name=name,

            D:\Apps\anaconda2\lib\site-packages\stl\stl.py in load(cls, fh, mode, speedups)
            69 try:
            70 name, data = cls._load_ascii(
            —> 71 fh, header, speedups=speedups)
            72 except RuntimeError as exception:
            73 # Disable fallbacks in ASCII mode

            D:\Apps\anaconda2\lib\site-packages\stl\stl.py in _load_ascii(cls, fh, header, speedups)
            216 iterator = cls._ascii_reader(fh, header)
            217 name = next(iterator)
            –> 218 return name, numpy.fromiter(iterator, dtype=cls.dtype)
            220 def save(self, filename, fh=None, mode=AUTOMATIC, update_normals=True):

            D:\Apps\anaconda2\lib\site-packages\stl\stl.py in _ascii_reader(cls, fh, header)
            193 # buffer and/or StringIO does not work.
            194 try:
            –> 195 normals = get(‘facet normal’)
            196 assert get() == b(‘outer loop’)
            197 v0 = get(‘vertex’)

            D:\Apps\anaconda2\lib\site-packages\stl\stl.py in get(prefix)
            173 else: # pragma: no cover
            174 raise RuntimeError(recoverable[0],
            –> 175 ‘Incorrect value %r’ % line)
            176 else:
            177 return b(line)

            RuntimeError: (True, “Incorrect value b’facet normal'”)

            In [6]:

          • Rick van Hattem | 2019-07-09 at 20:19:41 #

            It looks like your file is corrupt. There’s a ” after facet normal

  12. Louis Desdoigts | 2020-04-27 at 03:15:29 #

    HI Rick!

    Firstly I just wanted to thank you for your numpy-stl package! I’ve been using it to try and fabricate an optic for my research project. I am having an issue though with the physical dimensions of the output stl file being the wrong size. The way I create the file is by manually defining the vertices and edges that define the shape, but I can not seem to find the way to define the normal vector which if I understand correctly is what actually defines the physical dimension of the mesh object. Perhaps I have just missed where to define this, I was hoping you could point me in the right direction to figure out how to either scale a created mesh object or define this in the mesh.Mesh function (like some parameter that defines the scaling relationship between a unit of ‘1’ and a physical dimension).

    Also In using this package I wrote some code that can turn an 2d array of z-heights into a mesh object, basically creating a mesh object as if one were to ‘vacuum seal’ an array of heights if that makes sense. I was thinking I could maybe add this as a function into your numpy-stl library.

    Anyway let me know if there’s something I’m missing!

  13. Reshama Shaikh | 2020-12-09 at 22:45:08 #

    Would you be available and interested in doing a 30 minute presentation on sphinx? This would be to help newcomers to open source understand .rst files.

    Example videos:

    • Rick van Hattem | 2021-09-02 at 18:30:18 #

      I’m not the best person for that I think. While I’ve used Sphinx quite a bit, I’m by no means an expert

  14. Max Clark | 2021-02-16 at 13:39:27 #


    I’m have a little trouble with portalocker and would love some guidance if you have the time.

    I have two Google Colab instances with the same Google Drive mounted to each. I would I try running the code that you put here https://stackoverflow.com/a/39338942 with no success.

    This is what happens:
    1. Run first instance (no change to the file yet)
    2. Run second instance (no blocking/error occurs)
    3. I notice “second instance” has been written
    4. I provide input to the first instance
    5. The file is overwritten and says “first instance”

    It seems the second instance doesn’t realise the file is locked. Any idea what I’m doing wrong? Thanks in advance

    • Rick van Hattem | 2021-09-02 at 17:51:15 #

      The problem is likely that your Google Colab filesystem does not support locking. Alternatives could be to use the Redis locking that portalocker also provides but you would need a Redis server. I’m not sure if Google Colab offers that.

  15. Georgios Doumas | 2022-04-01 at 00:21:29 #

    Hello Rick, I see that a 2nd edition of your Mastering Python book is about to go out in May. I was thinking to start the 1st edition, but now that I know a 2nd edition is about to come, I will wait for it. My questions are : I noticed some Amazon reviews that were complaining about the english language used, and how the readers could not understand what you were trying to say. So I hope that you have improved on that. If I was aware 2-3 months ago that you were going to have a 2nd edition, I would offer you free reviewing and improvements (and I could catch almost all the typo mistakes). Anyway , I can even do that for you now.
    What I would like to ask is : in what way is your book different than “Serious Python” by Julien Danjou ?

    • Rick van Hattem | 2022-04-01 at 00:49:58 #

      I know the review you are mentioning and that sentence was indeed incorrect in the final version of the book. The irony is that the mistake was caused by the final grammatical review process because the person looking at the spelling/grammar didn’t know the difference between “a function” and “functional programming”.

      The new version has addressed all issues I could find in the reviews so I hope it will work out better this time 🙂

      With regards to “Serious Python”, I should note that I have not thoroughly read that book so I could be missing some parts. But from what I have seen, that book is far less in-depth.

      Some subjects that are covered in Mastering Python 2nd Edition that Serious Python does not appear to cover:

      – asyncio
      – f-strings
      – Python 3.10 pattern matching (the switch statement)
      – Scientific Python
      – Artificial Intelligence
      – Alternative interpreters such as ipython/jupyter/bpython/ptpython
      – Project dependency management (either using requirements.txt or using poetry/pipenv/etc.)
      – C/C++ extensions (native/cython/numba/etc.)

  16. Advik | 2022-04-26 at 15:05:44 #

    Hey rick. Have a nice day ❤
    Thank you for making my day better with all of your projects
    (portalocker, python-progressbar)

  17. Ravi | 2023-02-06 at 13:17:12 #

    Hi Rick – I am using numpy-stl version 3.0.0 in Mac jupyter. I have been struggling to solve this problem when I try to save stl in ASCII.

    newSTL.save(‘NewSTL.stl’, mode=stl.Mode.ASCII)

    error: module ‘stl’ has no attribute ‘Mode’

    Thankyou for your suggestion,
    best, Ravi

    • Rick van Hattem | 2023-03-06 at 12:52:51 #

      Usually these issues are caused by having a different stl module installed. Start in a fresh environment to be sure you don’t have any other stuff installed 🙂
      I recommend using poetry to manage your project


  1. wol.ph https: – dataala - 2022-07-07

    […] About Rick van Hattem (Wolph) | Wolph […]

Leave a Reply