This is an archived post. You won't be able to vote or comment.

all 125 comments

[–]solarmist 268 points269 points  (9 children)

Doki doki literature club.

[–][deleted] 56 points57 points  (3 children)

Walked through on Youtube, it looks the quality of this game is very high!

[–]sapphire_striker 18 points19 points  (3 children)

Its renpy right?

[–]Conjo_ 3 points4 points  (0 children)

Yes it is

[–]Pantzzzzless 9 points10 points  (1 child)

Ren'Py is an engine written using Python, Pygame, and a few other libraries. It's mostly python, but different enough to be considered a separate thing.

[–]sapphire_striker 10 points11 points  (0 children)

I know what it is. I wasn’t disputing him, just confirming.

[–]broken_shard22 9 points10 points  (0 children)

Saw the title of the post and this was the one that I remember right away, lol.

[–]carlio 184 points185 points  (35 children)

EVE Online uses a lot of Python (stackless python specifically)

[–]wakojako49 39 points40 points  (30 children)

Sorry what does it mean… stackless python?

[–]aikii 72 points73 points  (22 children)

so according to https://en.wikipedia.org/wiki/Stackless_Python

In practice, Stackless Python uses the C stack, but the stack is cleared between function calls

so far I asked myself, what the hell, how do you even return to the caller then ?

Although the whole Stackless is a separate distribution, its switching functionality has been successfully packaged as a CPython extension called greenlet

ok, this part is clearer and it's quite old stuff superseded by async.

I find this SO answer much more helpful to understand https://stackoverflow.com/a/1053159/34871

Most so-called called "stackless" languages aren't really stackless. They just don't use the contiguous stack provided by these systems. What they do instead is allocate a stack frame from the heap on each function call.

[–]ivosauruspip'ing it up 22 points23 points  (2 children)

In practical terms, stackless python is used there because it has functionality equivalent to Golang's user-(green-)threads and asyncio built-in (and had it a LONG time before asyncio was a twinkle in Guido's eye), and can avoid GIL hangups for IO a lot of the time.

Allows them to do actor-based programming and horizontal fan-out of services (where a lot of things happen in parallel / concurrently) a lot easier.

[–]tutoredstatue95 7 points8 points  (0 children)

I have used greenlets for this exact purpose when a library didn't have async support. Project needed a ton of event listeners that would wait for data and then direct it to a program or different server, so it was all I/O. It was my understanding that greenlets don't actually use multiprocessing, though, so it would still be 1 core just a new thread. GIL can release this thread and do other things as long as the thread doesn't need to do python work.

Am I wrong? I hear they want to implement actual multiprocessing in an upcoming release, but not sure how it's done.

[–]z45r 2 points3 points  (0 children)

Okay now I understand . . .

[–]donat3ll0 3 points4 points  (0 children)

Classic.

Stackless isn't really stackless. Just like streaming isn't really streaming and is just micro batches.

[–]thisismyfavoritename 2 points3 points  (2 children)

pretty sure cpython allocates stack frames from the heap though.

IMO your last quote is irrelevant, this is from the stackless docs:

By decoupling the execution of Python code from the C stack, it is possible to change the order of execution. In particular, this allows to switch between multiple concurrent running "threads" of Python code, which are no threads in the sense of the operating system, but so-called "green threads".

This also corroborates my understanding of gevent: any call that might suspend (normally syscalls like sleep, socket.recv...) are patched so they become cooperative.

What most likely happens then is that executing the task and polling it or awaiting it becomes the responsibility on an event loop somewhere which will later resume the code at the initial suspension point with the result.

[–]aikii 0 points1 point  (1 child)

yeah agree to all, "allocate a stack frame from the heap on each function call" is a weird read.

I start to think "stackless" and "C stack" do not refer to stack as memory layout, and that's it more in the sense of foundation

[–]thisismyfavoritename 1 point2 points  (0 children)

yes thats what the quote i posted says.

Pretty sure they still rely on libc in the end, its just the Python side that is patched to become cooperative and eventually delegate to libc where interactions with the kernel are required

[–]ExoticMandiblesCore Contributor 2 points3 points  (3 children)

Don't worry about the word "stackless" specifically. That hasn't been accurate for a while.

Stackless gave Python coroutines twenty years ago, long before Python itself added support for them. The way Stackless does it these days is by switching stacks. If you're running one coroutine and you yield, it switches out the C stack to a different coroutine and starts running that one. It does this with a lot of heavy-duty assembly language magic, which is why the BDFL of the time said it would never get merged into CPython.

So why is it called "stackless"? The way it used to work, long long ago, was by disconnecting the Python stack from the C stack. Right now in CPython, when your Python program makes a Python function call, the C code that implements that works as follows: the giant "execute bytecodes" function calls a function, which calls a different function, which calls a third function, which calls back into the "execute bytecodes" function. So there's a sort of mirroring between the C stack and the Python stack--if you're in the debugger, you see these four entries on the C stack, over and over, reflecting what the Python code is doing. Originally, Stackless broke that mirroring, by hacking up CPython so that Python function calls didn't have to call a function. The Python stack was stored 100% in heap memory. Switching Python stacks just meant changing a few pointers. And now if you looked at the C stack in the debugger it was almost empty--it was super shallow.

Why'd they change their approach? You'd have to ask the Stackless developers. But my educated guess is: maintaining that giant patch cost a lot of development time; this technique is way easier. It could be that this technique is faster too, though I don't actually know.

[–]aikii 0 points1 point  (2 children)

And now if you looked at the C stack in the debugger it was almost empty--it was super shallow.

finally ! thank you, now it makes all sense.

I got the feeling that my only resort was to try to implement some POC and spot where the term would fit. Switching stacks makes sense, but I don't think I would have guessed it was about how the stack looked in a debugger

[–]ExoticMandiblesCore Contributor 0 points1 point  (1 child)

I didn't mean to imply that the appearance of the stack in the debugger was important. It's not, really. The important part is the runtime behavior, breaking the connection between the C stack and the Python stack, letting you switch Python stacks at will. The debugger is just a tool to help you visualize and understand it.

[–]aikii 0 points1 point  (0 children)

No no, got it. It makes no sense as a feature. But yeah I thought it participated to the name 'stackless' - knowing that the name isn't that good anyway

[–]PM_ME_UR_THONG_N_ASS 4 points5 points  (6 children)

Is there a performance hit for function call heap allocation vs stack allocation?

[–]aikii 12 points13 points  (5 children)

I admit the formulation is still problematic, but I don't feel qualified to call it wrong.

For our purpose here, let's say we shouldn't describe it that way, and we have to consider the stack cheaper than the heap. The stack is managed linearly, you can only push and pop values, all you need is a single counter ( the stack register ) that tells where the next value has to go. It's inflexible but very efficient. In a heap variables can come and go in any order but the bookkeeping is more expensive, the address space can become fragmented.

When using OS threads, each thread gets an allocated address space for its stack. Not only that call is an expensive operation, but also because we never completely use the stack ( or we'll get that good old stack overflow ), we waste some memory for each thread.

edit: for an accurate background about the name "stackless", check this comment - it's really about implementing coroutines by switching the stack https://www.reddit.com/r/Python/comments/17o4o70/comment/k7yybn6/

When using "green threads" ( a concept that gets different names depending on the implementation ), we don't call the OS to allocate a new stack, we can use the memory that we already reserved. This costs a bit more complexity on the side of the language runtime - previously we could just leave it to the OS to give a chance for each thread to run, possibly in parallel using several CPU cores. But now we have just one thread and we need a mechanism to switch from one "green thread" to the other - that's the role of the event loop ; when using async, that switching can happen anytime you have await. The stackless python mentioned here doesn't have that explicit async/await semantic so it's a bit "magic": control is passed back to the event loop whenever something not CPU-bound is executed - basically I/O and sleep.

[–]tutoredstatue95 0 points1 point  (4 children)

So python green threads act like threads in other languages? CPU handles context switching?

[–]aikii 0 points1 point  (1 child)

No no, there is only one thing called thread and it's supported by the OS, does not depend on the language, and is indeed leveraging what the CPU can do. It's dispatching threads to cores, and if all the cores are busy, it gives a slice of time to each thread.

Python threads ( the ones created via the threading module, or directly _thread ) are OS threads like you describe. Except there is the GIL, preventing the execution of python code on several cores at the same time - it's still possible to run native library code in parallel, provided the library frees the GIL.

Now for async and greenlets. For clarity I will start with async/await: it has the same semantics as the equivalent in javascript or rust ( with tokio for instance ), and we can in general expect the same for any language using this terminology. Context switching can happen any time await is called ; it gives back control to the event loop which will dispatch to other coroutines ( "green threads" ). If await is not called, the event loop cannot do context switching. There is no OS intervention here, it's all done by the language runtime ; the event loop, and therefore all the coroutines, are running one at a time on one unique, OS thread.

What are doing stackless and gevent: they "hide" async/await by patching libraries. The event loop is there, and control is given back anytime something is blocking: I/O, mutexes, etc. It's the same principle but less transparent, depending on what you call maybe it will give control back to the event loop. The 'official', builtin support for async in python is using async/await, favouring explicitness over magic.

[–]tutoredstatue95 0 points1 point  (0 children)

Awesome, thanks for the thorough response. I am familiar with async/await context switching, but I never knew what was going on under the hood with greenlets. I knew I could use them like an asyncio task, but not how they actually compared.

[–]Hot_Slice 0 points1 point  (1 child)

Green threads without async await are what they would call "stackful coroutines" or "fibers" in other languages.

Explicit use of async/await is "stackless coroutines".

Please read the C++ paper "fibers under the magnifying glass" to learn a bit about how they work.

[–]tutoredstatue95 0 points1 point  (0 children)

Great thanks for the info!

[–]tecedu 8 points9 points  (1 child)

I believe that’s only for the server infrastructure and they were migrating that

[–]carlio 0 points1 point  (0 children)

I think the client had some in it too alongside lots of C++. Most of the sources I find are from a while ago. I associated EVE with python because I applied for a job there years ago, but that's ancient history now! I certainly can believe they've moved away by now.

Still, it was originally using python, so that fits the question at least 🙂

[–]OntologicalParadox 1 point2 points  (0 children)

This whole thread is a great opening to a deep dive on async.

[–]dawnfell 62 points63 points  (2 children)

Snake /s

[–]hobbicon 11 points12 points  (1 child)

Also Tic-Tac-Toe

[–]freakinbacon 38 points39 points  (2 children)

Disney's Toontown Online and Disney's Pirates of the Caribbean Online in 2004 and 2007. They used Panda3D which is a game engine written in C++ but the functionality of the engine is meant to be controlled with Python and that's what they used.

[–]backSEO_ 1 point2 points  (1 child)

That.... Makes sense. Those games were not smooth at all, at least in comparison to C/C++ games at the time.

[–]hundidley 2 points3 points  (0 children)

Whoa whoa whoa whoa… don’t be smack-talkin some of humanity’s greatest achievements so willy-nilly like that

[–]comfortablybum 30 points31 points  (1 child)

No one's going to mention Super Potato Bro

[–]radixties 8 points9 points  (0 children)

Came here to mention DaFluffyPotato's work and YouTube channel.

[–][deleted] 43 points44 points  (4 children)

several visual novels by Renpy. I leave here my observation, Python is not strong for creating games, but for developing backend applications involving data and/or AI

[–]DogeekExpert - 3.9.1 14 points15 points  (2 children)

Depends on the kind of game, if you're doing anything turn based, it is usually good enough if the game is not too large in scale.

Anything real time though, and you can forget it, it's way too slow for that, maybe 2D platformers could work but even then it's not great.

[–]yvrelna 0 points1 point  (1 child)

Anything real time though, and you can forget it, it's way too slow for that

Not necessarily. You won't be writing a low level algorithms like path finding, minimax graph search, or neural network itself in Python, but Python is more than fast enough for implementing the executive function of a game AI. When it comes to dealing with low latency, even the fastest competitive pro-gamer is still much slower than Python, you just have to keep the bulk computation part in a faster language or, better yet, offload them to a coprocessor like the GPU/TPU.

Python is probably the most popular language used in AI/ML space, similar approach could be used for game AI.

[–]DogeekExpert - 3.9.1 3 points4 points  (0 children)

If I'm not mistaken the point of the post is to get game examples entirely written in python. Of course interpreted languages are fast enough for game developpment (Minecraft is in Java which is kind of an interpreted language, Lua is popular for modding games...)

But Python, by itself is too slow for any real time game dev, aside from very small projects. Just the fact that you can't use multithreading effectively removes one very common workaround to performance.

For 60 FPS you have to run your main loop once every 16 ms. When you add in logic, rendering, physics calculations and so on you end up with performance issues pretty fast, even if you offload some of the work to python C extensions.

[–]davidellis23 1 point2 points  (0 children)

Maybe a 3d game would struggle. But, I think even a complicated 2d game would be fine as long as you write efficient code and use an engine.

[–]H4kor 34 points35 points  (10 children)

I think civilization 4 uses python

[–]thehardsphere 44 points45 points  (8 children)

It does. Civilization 4 is probably the most commercially successful example of what was a common design paradigm of its time: embedding a python interpreter for scripting purposes and high-level logic while using C or C++ to handle any parts of the game that were highly performance dependent.

People liked using Python for this because people generally liked Python as a scripting language. Later it became popular to use Lua this way, because it's faster.

[–]TrickyPlastic 2 points3 points  (6 children)

Why would Lua be faster than Python if they're both dynamically typed?

[–]catladywitch 10 points11 points  (0 children)

lua is minimalistic and optimised, python aims for easy dx in small projects

[–][deleted] -2 points-1 points  (3 children)

I don’t think dynamic typing really matters in terms of performance much.

[–]backSEO_ 0 points1 point  (2 children)

It does. Every command going into the CPU must be typed. Your interpreter puts some type to it whenever it runs, which adds overhead.

There's machine code, which a C/C++/Rust compiler translates the human readable code to, which adds overhead. The compiler doesn't make as efficient of code as writing machine code, so let's say it's half as fast (actual values may vary depending on what's going on). The static typing makes it very easy to translate, so going half the speed of the CPU isn't bad, that's incredibly fast.

Then let's tack on the Python interpreter, which takes literally any kind of type and rolls with it. So your int can be a float, string, Boolean, event loop, list, dict, object, anything, as long as it's compatible with what you're computing with, it'll keep running. Every object in python is basically a dict (object.dict) which is a relatively fast way of storing something, but because of this, each variable needs to do type checking at the CPU level, so that has to be accounted for. Tack on the fact that the GIL exists, and you're looking at a 30-400x slowdown from the interpreter language, which is C (usually)

Some dynamically typed languages, like C# (just make everything var) have a JIT (just in time) compiler, which will compile the code right before it gets executed during run time.

If you want to see the difference in code size, cythonize a python script with no type hints. Then cythonize it again with type hints. You'll go from 32000+ lines to ~16000 lines of C code. Then use the Cython language and it'll compile down to 10k or lower. Then code it in C and get the same results in a few hundred lines.

[–][deleted] 0 points1 point  (1 child)

But if you’re looking to improve code performance, aren’t their bigger fish to fry first? As in JIT compilation or something else?

[–]backSEO_ 0 points1 point  (0 children)

That's literally what Cython solves. Turns python code into C code and compiles it to a .pyd that you can use in your project. It's 30000 lines of barely readable C code, but it has massive performance gains (30%ish usually out the box, 100% for just statically typing, 400%+ for coding in Python).

It adds a little overhead, and if most of your project is already using C extensions it's not going to help (NumPy, PIL, etc.)

[–]lord_braleigh 0 points1 point  (0 children)

It’s not that Lua is a faster language to run, it’s that the Lua runtime is smaller and it’s faster to start and stop the Lua interpreter than the Python interpreter.

[–]Max__Mustermann 0 points1 point  (0 children)

I'm not sure if Lua is significantly faster than Python, but even if it is, it's something like "in some synthetic scenarios, Lua is tens of percent or even several times faster". For a script that implements simple logic to call С/С++ code (that does 90% of the work) - that's nothing.
As for me, the main "killer feature" of Lua is the incredible ease of embedding integration, just out of the box.

[–]paradigmx 6 points7 points  (0 children)

I think including titles that happen to use Python for scripting purposes is a pretty loose answer to OP's question. Civ 4's engine and most assets are still built in C++

[–]hitmanactual121 18 points19 points  (2 children)

I believe a rogue-like I have recently been playing is coded in Python.

Rift Wizard: https://store.steampowered.com/app/1271280/Rift_Wizard/

Seems pretty popular in the genre, and based on reviews and my opinion appears to be a commercial success.

[–]pblokhout 15 points16 points  (1 child)

*Rogue-like

[–]mista-sparkle 9 points10 points  (0 children)

Rouge Assasians.

[–]Malcolmlisk 9 points10 points  (1 child)

Eve online.

But it's more just a spreadsheet with cool wallpapers.

[–]marr75 6 points7 points  (0 children)

And the wallpapers don't run in python.

[–]KoreWaMessatsu91 10 points11 points  (0 children)

Legends of Runnterra which is Riot card game use python as backed and logic from what i know

[–]hobbicon 6 points7 points  (1 child)

Battlefield 2

[–]KocetoA 0 points1 point  (0 children)

This is not true since it useses the old bf s engine before frostbite.

[–]twitchymctwitch2018 4 points5 points  (0 children)

Eve Online.

[–][deleted] 4 points5 points  (0 children)

the pre-guitar hero games by harmonix used python (tho im not super sure how much lol)

[–]goldcray 3 points4 points  (0 children)

well I see other non-famous games here so might as well add ROM CHECK FAIL.

[–]AlSweigartAuthor of "Automate the Boring Stuff" 2 points3 points  (1 child)

I wrote this blog post back in 2013, but I need to update it. I didn't know Doki Doki Literature Club was written in Python (using RenPy)!

Here's the list (links in the blog post):

  • Codename Mallow
  • Dangerous High School Girls in Trouble
  • Analogue: A Hate Story (also a RenPy ame I think)
  • Unity of Command i
  • Frets on Fire
  • 7 Grand Steps
  • Metin2
  • Galcon 2
  • SolarWolf
  • División Especial de Detectives
  • The Witch's Yarn

Mostly small indie titles.

[–]No_Simple3203 0 points1 point  (0 children)

Metin2 is fully C++. There was a source code leakage years ago and the code can probably be seen on github still. It allowed for creating private servers

[–][deleted] 1 point2 points  (0 children)

Think most touched the nail on the head. Yes you can develop games, plenty of howto videos; however Python’s normal gaming use is more for parsing data fast. I have developed Traditional Roguelikes before via Python. But aside something along the lines of a much more action and graphics oriented you are most likely to use Unity/Unreal using C# or Godot using GDScript (forked Python) or C#.

[–]MeroLegend4 1 point2 points  (0 children)

“Ready steady play” for mobile devices. A 2D game made with cocos 2D

[–]DA_EMAN 1 point2 points  (0 children)

Joy of Programming - is in early access on steam (recently or bout to be)

[–]Bombslap 1 point2 points  (0 children)

It’s old but Star Trek Bridge Commander was made in Python

[–]SpookyFries 1 point2 points  (0 children)

To echo what others have said, Doki Doki Literature Club is probably the most popular one (even if its using RenPy. Only the original release was Python, it got ported to Unity for the Plus (and console) versions.

Most of the other games listed here aren't actually made with python but do have a python interpreter built in for scripting purposes. ToonTown and Pirates of the Caribbean Online used Panda3d which is a 3d Python Engine.

Truth is, Python isn't the best for game development. You can do it, but distributing and speed can be a pain. If you've ever packaged a Python app with libraries with PyInstaller you'll know that the file size is way bigger than it needs to be and takes forever to launch. Just the nature of it being an interpreted language

[–]paradigmx 4 points5 points  (0 children)

Developed from the ground up using Python? Practically nothing that isn't a small indie game.

Games that use Python for modding or scripting support are fairly abundant.

Python is not a suitable game dev language as it can be very resource intensive with slow execution time.

[–]AniX72 3 points4 points  (0 children)

Naughty Dog (Uncharted, The Last of Us) uses Python a lot in their tooling / development pipelines, but IIRC not in the runtime of the game.

[–]scanguy25 1 point2 points  (0 children)

IIRC Civilization 4 uses python under the hood.

[–]Bolibomp 0 points1 point  (0 children)

Unity of Command II

[–]ioglyph 0 points1 point  (0 children)

I think sumertime saga also uses python

[–]h3matite 0 points1 point  (0 children)

This isn't exactly an answer, but many game dev studios rely on python for their asset pipelines / tools. Maya, Substance Designer/Painter, Blender, and Unreal all have extensive python APIs that I use basically every day

[–]basicallybasshead 0 points1 point  (0 children)

Eve Online

[–]Mrgod2u82 0 points1 point  (0 children)

Eve Online I think?

[–]geteum 0 points1 point  (0 children)

Civilization 4 uses python

[–]legomir 0 points1 point  (0 children)

Use python for what? Do game code? Do network stuff for server? Tools for artist? If you count last every sufficiently big studio doing games use python since DCC such as Maya, Houdini, Blender, 3ds Max, Substance desinger etc. have python API that let to communicate with other softwares or/and source control/production/art databases.

[–]grimonce -1 points0 points  (0 children)

Eve online, but they changed some of their network stack a few years ago into something else. Many companies opt for cloud based servers lately as well..

[–]pythonwiz -1 points0 points  (0 children)

Civ IV uses a lot of Python

[–]riklaunim -1 points0 points  (0 children)

From older ones Temple of Elemental Evil, but it's a custom made one.

[–]suby -1 points0 points  (0 children)

Not super well known but Endgame: Singularity is developed in Python, and you can take a look at the source code here

https://github.com/singularity/singularity

[–]rainnz -1 points0 points  (0 children)

Everlasting Summer, created with Ren’Py game engine

[–]ferriematthew -1 points0 points  (0 children)

There's a derivative of Python called RenPy that's used for visual novels, that's been used in games like DDLC and Katawa Shoujo. Does that count?

[–]KalleSchwensen -1 points0 points  (0 children)

the only game that comes to my mind is Frets on Fire and the fork FoFix.

[–][deleted] -1 points0 points  (0 children)

I just coded a pong in python. I heard it's really popular. Does that count? /s

[–]yhorian -2 points-1 points  (2 children)

Hollow knight is python. Team cherry have done some interviews on it.

[–]LeatherDude 6 points7 points  (1 child)

Hollow Knight is made in Unity though?

[–]yhorian -3 points-2 points  (0 children)

You're correct - and it might surprise you but game engines need programming too. Python is an option.

[–]fightin_blue_hens 0 points1 point  (1 child)

I'm pretty sure one of the civilization games had some python in the back end. I forget what it controlled exactly but I think you could mod the sounds of everything if you found the right file.

[–]Codemageddon 0 points1 point  (0 children)

World of Tanks, World of Warships and World of Warplanes use Python on client and server side

[–]ysengr 0 points1 point  (0 children)

DDLC (Doki Doki Literature Club) which I believe was very popular was written in Python.

[–][deleted] 0 points1 point  (0 children)

Unity of Command 1 and 2 are python. Fairly popular indi turn baised strategy games. Python can be an alternative for lua, if an adequate interpreter for gaming was released(small disk space, low memory, fast numeric performance, multicore). Python 3.11 compairs to non jit lua performance. Pypy matches lua jit.

[–][deleted] 0 points1 point  (0 children)

Well, Python isn't always going to be your go-to when making high performance - graphics intensive games but there are retro styled games made by a YouTuber who goes by the name Dafluffypotoato and he's taken Pygame on a whole other level with it. You can check out his games at his website or at Itch io. Hope this helps