tensorflow
exception-handling
debugging
deep-learning
machine-learning

Tensorflow Print doesn't print anything if exception is thrown during downstream operations

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If tf.print produces no output when a downstream TensorFlow operation fails, the reason is usually execution order. In graph-style execution, tf.print is itself an operation with side effects, and if the failing path aborts the step before that print operation is guaranteed to run, you may never see the message.

Why tf.print Is Different from Python print

Python's built-in print() executes immediately. tf.print, by contrast, becomes part of the TensorFlow execution graph and only runs when the graph runtime executes it.

That distinction matters. If your graph contains a print op but the session never actually reaches it, or if another op fails first, there is nothing to flush to standard output.

Here is a TensorFlow 1 style example where the print op exists but is not guaranteed to run before the failure:

python
1import tensorflow as tf
2
3tf.compat.v1.disable_eager_execution()
4
5x = tf.constant([1.0, 2.0])
6print_op = tf.print("x =", x)
7bad_op = tf.math.divide(x, 0.0)
8
9with tf.compat.v1.Session() as sess:
10    sess.run(bad_op)

The graph contains print_op, but sess.run(bad_op) does not fetch it, so TensorFlow has no reason to execute it.

Make the Print a Dependency

If you want tf.print to run before another op, connect it with a control dependency.

python
1import tensorflow as tf
2
3tf.compat.v1.disable_eager_execution()
4
5x = tf.constant([1.0, 2.0])
6
7with tf.control_dependencies([tf.print("x =", x)]):
8    checked = tf.identity(x)
9
10bad_op = tf.math.divide(checked, 0.0)
11
12with tf.compat.v1.Session() as sess:
13    sess.run(bad_op)

Now the print op is on the required path, so TensorFlow must execute it before evaluating bad_op.

Fetch the Print Explicitly

Another debugging option is to fetch the print-related op directly or bundle it with the computation you are running.

python
1import tensorflow as tf
2
3tf.compat.v1.disable_eager_execution()
4
5x = tf.constant([1.0, 2.0])
6print_op = tf.print("x =", x)
7safe_value = tf.reduce_sum(x)
8
9with tf.compat.v1.Session() as sess:
10    sess.run([print_op, safe_value])

That is useful when you are narrowing down where the graph starts to fail.

Eager Execution Changes the Experience

In TensorFlow 2 eager mode, tf.print is usually more intuitive because operations run immediately. If the print statement executes before the failing line, you typically see the output.

python
1import tensorflow as tf
2
3x = tf.constant([1.0, 2.0])
4tf.print("x =", x)
5tf.debugging.assert_all_finite(x / 0.0, "Non-finite value detected")

Even there, though, exceptions can still interrupt execution before later print calls run. The principle is the same: only already-executed side effects become visible.

Better TensorFlow Debugging Tools

For numerical failures, tf.debugging utilities are often more reliable than ad hoc print statements.

python
1import tensorflow as tf
2
3def safe_divide(x):
4    result = x / 0.0
5    tf.debugging.assert_all_finite(result, "Division produced non-finite values")
6    return result

Assertions fail with clearer intent and are easier to keep in the graph than temporary print statements.

You can also break complex expressions into intermediate tensors so you can inspect smaller pieces without relying on one large failing op.

Common Pitfalls

The biggest pitfall is assuming that creating a tf.print op means it will automatically run. It will not unless it becomes part of the executed fetch path.

Another mistake is placing the print logically near the failing code but not actually linking it through dependencies. In graph execution, visual proximity in Python source code does not guarantee runtime order.

Developers also sometimes use tf.print when a Python print() or a direct eager inspection would be simpler. If you are already in eager mode, ordinary Python debugging tools may be easier.

Finally, if an exception occurs in a compiled graph function, the runtime may stop before buffered side effects appear, so do not treat missing print output as proof that the value was never computed.

Summary

  • 'tf.print is a TensorFlow op, not an immediate Python print statement.'
  • If a downstream failure aborts execution before the print op runs, you will see no output.
  • Use control dependencies or explicit fetches when you need the print to execute first.
  • In eager mode, tf.print is more immediate, but exceptions can still stop later prints.
  • For serious debugging, tf.debugging assertions are often more reliable than print statements alone.

Course illustration
Course illustration

All Rights Reserved.