It will be hard to find guidance for Python in safety critical software development because there are too many things that make Python no option for really critical applications. You could never entrust a piece of Python code your life. See a few reasons why:
The memory model in Python is much different then the one in languages for embedded software. Python uses massively the Heap, while safety critical software normally uses global data and the Stack. For dynamic memory it is just too complicated to perform a safety assessment. You have phenomenon like memory fragmentation, garbage collection, memory leaks. The algorithms in Python, that prevents these things, have never been qualified.
In Python you normally don't care for dependencies, cyclic dependencies. As everything is interpreted at runtime, it just works. But safety critical applications normally require that you have a Top-Down design with abstraction levels and dependencies in a tree structure. Because this is, what the V-Model wants. That is the reason why Python code most of the times is not compliant to safety standards.
Of course in Python it is as easy as in languages lika Ada or C to write good and certifiable code that follows certain design principles. But it is also as easy as writing code that does not follow good design principles. That means it is harder to convince the authorities that you follow the right principles. With "right" principles I mean that the authorities want to see what you consider as your principles. You have to define that. With Python you would start from an empty paper. And then you have to convince the authorities that these are really appropriate principles and that you are compliant to them. Most teams would not even have the skills to define their own rules. The certification liaison is then a lottery. Example of such principles, you can see here or here
For example in Python it is normally not a problem that Low-Level functions call High-Level functions. You can just do that. But statically typed langauges would not compile in this case. They force you to establish Dependencies in a stricter way. In practice it is extremely hard to establish such principles and convince developers of them if the compiler does not enforce this. For example the Dependency Inversion Principle, which you do often in Object Oriented Design is not something, that is easy and obvious for developers. It is hard to establish that mindset, especially in teams that have more an Embedded Software or hardware background.
Python developers prefer a defensive style of programming, so that the code is immune against adverse unexpected situations. But in safety critical code all situations must be taken into account in advance. Defensive programming prevents the detection of design errors early in the development.
For things like lambda expressions and closures it is hard to use test coverage metrics. But these are required in safety critical software development. You at least need to cover each Python statement once because without static typing, testing is extreme important. Otherwise you would not reliably identify type errors.
I understand that you don't expect that level of safety and that you just want to have certain (the best possible) level of safety. It would indeed be interesting to have guidance what features of Python can be considered as safe and what programming techniques are recommended. Unfortunately there seems to be no guidance available, yet. Perhaps people are worried too much about the run time environment and the concepts of Python not been mature enough or adecuate for safety critical applications.
A good book for reading is "Developing Safety-Critical Software - A Practical Guide for Aviation Software and DO-178C Compliance" by Leanna Rierson. It gives very interesting insights about what you have to care when developing safety critical software. It covers even things like Object Oriented Programming. When it comes to C# or Java it is said, that these languages are just not mature enough. And it can be supposed that the same is the case for Python.
I end this with a practical example. In safety critical applications the program must be deterministic. The program behaviour must be already known and predictable at "certification time". But see this code:
def print_message(msg):
print(msg)
def print_in_capital_letters(msg):
print(msg.upper())
print_message("Hello")
if i_want_capital_letters:
print_message = print_in_capital_letters
print_message("Hello")
It is hard to make clear statements about the behaviour of print_message
. It depends on the value of i_want_capital_letters
at runtime. Such dynamic behaviour is hard to bring in line with certification requirements. The certification authorities want to hear what the behaviour of the code actually IS and not that it depends on something, that is comming from the user. That sort of flexibility is probably a reason why Python became so popular. When trying to avoid such features, it makes probably no sense to use Python, at all.
The problem with the example is not so much, that the program behaviour changes due to user input. It is just not obvious, that the bahaviour of print_message
is permanently changed. There is nothing like a status variable that makes this change visible. It is even hard to find out, what the behaviour in certain moment in time is.
(You may argue, that this example is already an exotic use case, that does not happen so often. But this is actually the way how things for Unit Testing purposes are isolated. All things that do not belong to the "unit under test" are "stubbed" away using exactly this mechanism of the example. But the valid question of the certification authorities is then, if you have really tested the operational code or some manipulated code. For programming languages that use static typing, the type system provides "some" sort of confidence, that a stubbing mechanism does not change the semantic of the program, while in Python many things can be changed at runtime.)
A final show stopper for critical applications is the runtime system of Python. Safety critical software must be 100% reliable. That includes each Assembler instruction that is ever executed. If you compile a piece of C code, normally you get in Assembler quite exactly what you have written in that C code. Projects with a high level of safety requirements even have a process that verifies that the Assembler code fully traces to the C code. If you don't use any libraries there is no software pieces between your C code an the operating system or bare metal. All this means, the verification (e.g. testing) of your running Assembler code (and your product) can be done by verifying (e.g. testing) the C code. There is nothing (or at least not much) more. In Python this is different. Python is interpreted or at least executed on a basis of bytecode. That means that the Python interpreter is part of your product. But the Python interpreter is an Open Source project, that is completely out of your control. It has never been developed with a focus on safety. It is simply not possible to certify a product if safety was not taken into account from begin on. The Python interpreter would never be certifiable.