What is the issue with system() ?
With system() you have construct a command string which is then passed to a shell (like bash, csh, zsh, ...) which will parse it before invoking the desired executable. That means in constructing the command string you need to escape characters which have special meaning to the shell.
You can avoid the shell by using a call like subprocess.Popen() which will invoke the target executable directly.
The commands in this case are system administrator commands requiring sudo. sudo is not that standard across distros and may prompt for a password, which python may or may not honor properly and sudo might object on some systems anyway.
Admin commands should be handled elsewhere by the OS at boot. The file in question depends on the distro. Often there is a gui or /etc/network/config or the like where you can define interfaces. You can start with a batch script just. Might be worth looking into "Virtual Env" which is almost essential for managing dependencies during dev without having to install them all into your own system (and any users system) manually each time. I believe it also has the ability to run "init scripts". Thus when you "go into" that project, you run ". bin/activate" and it sets up your shell, environment, pythong interp, install the required deps for the project, runs your init script to make sure your interfaces are there etc.
The use of shell commands from within the application, hard couples the script to the shell, hardware and setup in question. It should be sufficient to make it an init check in the code.
Can I open the canbus interface? Does it exist? No? Exit with "Read the readme.txt bozo".
For my ROM programer for instance, the first things it does is open the file you gave it OR fail, then open the serial device you passed it as an arg OR fail. Fail first, fail fast, simplify the remaining puzzle.
It's something you can refine as you go though. There may be permissions issues if you want to refrain from running python as root. Such as you user needs to be in the group able to access the /dev/whatevers for your canbus interface.
EDIT: You know what I find amazing. The difference between "PoC", tutorial, chatgpt code and "complete" code. Even just build environment setup generates work and maintenance. Then you have things like checking and detainting parameters, system dependency detection, user errors, usage pages. Permissions. Different shells. Windows support so yo can dev on the corporate laptop. Handling actual command line arguments, using conventional -- and - "gopt" etc. Then your first user says, "But I'm on Solaris" and your boss says, "No, you can't just tell him where to go.". Logging code. Auditing code. Unit tests, intergration tests, test harnesses, test data, readmes, installer metafiles, repository meta files. Your "one file with 50 lines" very rapidly becomes a git repo with 100 files and 10Mb.
The good news is, if the code is only for you and you don't care, then don't bother. I have PoC scripts that have been running 24/7 with 99.99999% uptime for years and they still do their job. I have copy pasta ESP32 code written in about 1 minute that has been sending me data about my heating from a kitchen cupboard for 5 years straight and it's never once complained it didn't have proper error handling or unit tests. Usually dumb and simple works for simple things. Software does not scale well in complexity and the human mind though. So even hobby projects can get out of hand and impossible to work on rapidly as they "evolve", so "code hygene" and "best practice" should not be entirely overlooked. Also. Always be keen to refactor and redesign.