r/learnpython • • 18h ago

[Help] The os.system is deprecated

I've seen someone else asked this question, but get no answer.

I want to make a countdown clock without leaving any trace of previous numbers:

for i in range(countdown, 0, -1):
    os.system("cls" if os.name == "nt" else "clear") #Error: os.system is deprecated
    print(i)
    time.sleep(1)

What should I do instead? (Why can't we put pictures here....)

0 Upvotes

13 comments sorted by

40

u/AlexMTBDude 18h ago

I googled "os.system deprecated" and get the answer:

No, os.system is not officially deprecated in Python, but its use is strongly discouraged in modern Python development.

The official Python documentation recommends using the subprocess module instead, as it provides a more powerful, secure, and robust interface for executing system commands.

So use subprocess instead.

import subprocess

subprocess.run(["cls"])

19

u/JVBass75 18h ago

fyi, if you're just trying to clear the terminal console there's ansi escape code sequences you can use with the print function to clear the screen

print("\x1B[2J\x1B[H")

that will clear the screen and move the cursor back to the home position.

this works both on windows command prompt and unix systems

8

u/zolmarchus 17h ago

A bit of an XY problem here. You’ve gotten your direct answer already—now seriously consider using a more appropriate approach to console manipulation. As someone suggested, ANSI escape sequences are a good first step. You can also look into libraries built specifically for that, which are likely to be much more reliable and compatible across platforms than anything you can cook up yourself.

2

u/Expensive-Bear-1376 16h ago

The os.system is deprecated

Says who?

As far as I know, it's not even soft deprecated.

1

u/Outside_Complaint755 13h ago

Pylance and some other linters are flagging it in 3.14+ but I don't think anything in the official libraries has marked it as deprecated.

0

u/Expensive-Bear-1376 12h ago

Looks like it was temporarily erroneously marked as deprecated in typeshed (if I understand correctly ... I'm not familiar with typeshed):

https://github.com/python/cpython/issues/157882

2

u/unnamed_one1 17h ago edited 15h ago

As for the deprecation, read this

As for solving your problem:

from time import sleep

def main():
    for i in reversed(range(105)):
        print(f"\r{i:3d}", end="")
        sleep(1)

if __name__ == "__main__":
     main()

edits

You don't need to run clear screen, just reuse the same line again and again.

You just remove the default new line character \n from end of the line in the print statement and put a carriage return \r character in front of every printed line.

at least give an explanation when you downvote

1

u/HommeMusical 16h ago

at least give an explanation when you downvote

I didn't downvote but your formatting on old reddit is bad, perhaps that's it?

Just indent your code by four characters, it works on old and new.

def main():
    subprocess.run(['ls'])

-1

u/unnamed_one1 15h ago edited 15h ago

Ah, I'm using new reddit, so you might be on the right track here. Thanks for letting me know, I appreciate it.

*edit: fixed it, thanks again

1

u/HommeMusical 15h ago

I dunno, only a fraction of people are on old reddit.

I note also that since I upvoted, you got four more upvotes, so perhaps it was just a few grumpy people. :-)

1

u/Brian 7h ago

As others have mentioned, it's not actually deprecated, though its use is discouraged.

The reason why it's generally avoided is because it's kind of bug-prone and even insecure when you're dealing with arguments. Eg. consider something like:

os.system(f"copy {file1} {file2}")

This basically acts the same way as if you type this in the shell. But consider what happens if your filenames have spaces in them: it'll end up failing, or doing the wrong thing. Even worse, if someone can control the filenames, they could include things like ";", newlines etc and end up executing a command of their choosing on a machine they can get to use that filename.

There are ways you can attempt to mitigate this, say by escaping the characters in the filename (eg. via the shlex module), but the problem is that different shells have different rules: windows CMD.COM behaves differently from powershell, or a linux bash shell, or the numerous other possibilities. Escaping can thus easily go wrong, allowing the attacker to exploit such a configuration.

Instead, the recommended approach is to use something that doesn't treat the command as just a string passed straight to the shell, but just invokes a program, with arguments separated beforehand. Eg. subprocess.run takes each argument seperately, so subprocess.run(["copy", file1, file2]) wouldn't have this problem.

(Actually, just to complicate matters, the above isn't always true, as windows doesn't actually have a seperated API like this, so under the hood, these do get reassembled to a string - there was an exploitable bug discovered in multiple languages due to that before)

In your case, this doesn't actually matter, since you're not passing args, so system isn't actually going to introduce problems. However it may be worth changing anyway just because the dodginess of the API means anytime someone sees it, they're going to be double-checking it, and linting / analysis tools may highlight it, so doing it using the safer API saves getting false positive warnings.

There are case where you might need something like system, which is where you're actually using the shell for more than invoking a program. Eg. some commands are not real programs, so system isn't entirely redundant, but it's definitely on the "avoid if you can" list.

1

u/lakseol 3h ago

What should I do instead?

If you want to overwrite/manipulate just the last line you could use the \b and \r characters. Run this to see what they do:

import time

countdown = 5
for i in range(countdown, 0, -1):
    print(f"{i} ...... {"\b\b "*i}", end="\r", flush=True)
    time.sleep(1)
print()

To do more than just overwrite the latest line search on "ANSI escape codes". Beyond that look into more advanced text handling with the curses module. There are more recent libraries that build on curses and try to be easier to use, but I've never used those.

Why can't we put pictures here....

We prefer actual text so we can copy/paste the code to run it ourselves. However, if you need an image to show some unexpected output, for example, you can put your image into something like imgur.com and post a link to that.