Przestań wpisywać te same 4 polecenia: Jak prosty skrypt Pythona oszczędza mi czas każdego dnia
Każdy programista ma rytuał przygotowawczy, zanim rozpocznie swój dzień. Mój był niekwestionowany przez prawie dwa lata - były to cztery polecenia terminala, wpisywane w tej samej kolejności każdego ranka. Nie wydawało się to problemem, dopóki ostatnio tego nie zmierzyłem; czas, pominięte kroki i późniejsze debugowanie wszystko się sumowały. Więc napisałem skrypt w Pythonie, aby je zastąpić, i stał się on najbardziej użyteczną rzeczą w moim środowisku programistycznym.
Cztery rozkazy
Dlaczego każda z tych komend była nie do negocjacji
Jeśli pracowałeś nad jakimkolwiek projektem w Pythonie w środowisku zespołowym, prawdopodobnie uruchomiłeś wszystkie cztery. Każdy z nich rozwiązał problem w moim przepływie pracy:
git status- To polecenie ujawniło niezatwierdzone lokalne zmiany przed pobraniem. Uruchomienie go najpierw zapobiegło chaotycznym sytuacjom scalania, które pojawiają się, gdy pobierasz zmiany nad pracę, którą zapomniałeś zmodyfikować.git pull origin main- To synchronizuje moją lokalną gałąź z najnowszymi zmianami w repozytorium. Pominięcie tego oznacza, że mogę spędzić godziny pracując na przestarzałej bazie kodu i napotkać konflikty scalania, gdy trudniej je debugować.pip install -r requirements.txt- uruchamiam to, aby zainstalować wszystkie zależności, które moi koledzy mogli dodać od mojego ostatniego uruchomienia. Jeśli to pominę, zwłaszcza po zmianie gałęzi, zazwyczaj kończę na ściganiu komunikatów o błędach, które wyglądają jak prawdziwe błędy, ale w rzeczywistości są po prostu brakującymi pakietami.export DEBUG=true- To polecenie włącza szczegółowe logowanie i wyłącza niektóre zabezpieczenia przeznaczone wyłącznie dla środowiska produkcyjnego podczas lokalnego programowania. Każda nowa sesja terminala zaczyna się bez tego ustawienia, więc pominięcie polecenia export powodowało ciche błędy, które były trudne i frustrujące do zdiagnozowania.
Rodzimy skrypt i jego błędy
Początkowe rozwiązanie działało bez błędów, ale było niepoprawne w dwóch istotnych miejscach
Mój pierwszy instynkt był, aby owinąć wszystkie cztery w wywołania subprocess. Na początku wyglądało to schludnie, ale nie działało poprawnie.
## Don't do this
import subprocess
subprocess.run("git status", shell=True)
subprocess.run("git pull origin main", shell=True)
subprocess.run("pip install -r requirements.txt", shell=True)
subprocess.run("export DEBUG=true", shell=True) ## This does not make any changeBłąd 1: export DEBUG=true nic nie robi
Polecenie export jest poleceniem wbudowanym w powłokę. Kiedy jest wywoływane za pomocą subprocess.run(), działa wewnątrz procesu potomnego, który kończy się w momencie zwrócenia wywołania. Zmienne środowiskowe, które ustawiłem w procesie potomnym, nigdy nie dotarły do powłoki nadrzędnej. Polecenie wykonało się, zgłosiło sukces, a moja sesja terminala pozostała niezmieniona, bez zwracania błędu ani ostrzeżenia.
Błąd 2: Brak obsługi błędów oznaczał ciche awarie
subprocess.run() nie zgłasza wyjątku, gdy polecenie zakończy się niepowodzeniem, zwracało kod wyjścia różny od zera, który musiałem sprawdzić samodzielnie. W natywnym skrypcie, jeśli git pull nie powiedzie się z powodu problemów z siecią, skrypt kontynuuje działanie, instaluje pakiety na przestarzałej bazie kodu i zaczynasz dzień nie mając pojęcia, że coś poszło nie tak.
Skrypt, który działał
Mój drugi skrypt obsługiwał błędy, działał poprawnie i robi dokładnie to, co twierdzi
Dodałem alias, który sprawia, że uruchamianie skryptu jest jeszcze krótsze, za pomocą polecenia dev. Oto wersja, którą uruchamiam teraz, z obsługą wszystkich czterech zadań poprawnie i z wbudowaną obsługą błędów od samego początku.
import subprocess
import os
import sys
# The central helper - every command runs through here.
# Prints what it's doing, captures the output and exits with debugging information on failure
def run(command, description):
print(f"-> {description}...")
result = subprocess.run(
command, shell=True, capture_output=True, text=True
)
if result.returncode != 0:
# stop immediately and show error
print(f" FAILED: {result.stderr.strip()}")
sys.exit(1)
print(" Done")
return result
# Checks for uncommitted changes before pulling.
# Warns instead of blocking — the developer decides what to do.
def check_repo_state():
result = run("git status --porcelain", "Checking repo state")
if result.stdout.strip():
print(" Warning: uncommitted changes detected.")
# Syncs the local branch with the remote.
# Halts the script if the pull fails (e.g. no network connection).
def pull_latest():
run("git pull origin main", "Pulling latest from main")
# Installs any new dependencies since the last session.
# -q suppresses already-satisfied output so real changes are easy to spot.
def install_dependencies():
run(
"pip install -r requirements.txt -q",
"Installing/verifying dependencies"
)
def start_server():
print("-> Starting dev server (DEBUG=true)...")
# Copy the current environment so we don't mutate os.environ globally
env = os.environ.copy()
# Set DEBUG here instead of using export — variables set in a subprocess
# don't persist to the parent shell, so this is the correct approach.
env["DEBUG"] = "true"
# Pass the modified environment directly to the server process.
# DEBUG stays alive for the full lifetime of the server.
subprocess.run(["python", "manage.py", "runserver"], env=env)
# Runs all steps in the correct order.
# If any step fails, the script stops before reaching the next one.
def main():
print("\n Starting dev environment...\n")
check_repo_state()
pull_latest()
install_dependencies()
start_server()
if __name__ == "__main__":
main()Co się zmieniło po codziennym stosowaniu tego
Pominięte kroki zniknęły, błędy stały się bardziej zrozumiałe, a wdrożenie stało się prostym jednowierszowym procesem
Najbardziej nieoczekiwaną korzyścią było wprowadzenie nowych osób do pracy. Kilka tygodni po napisaniu skryptu przygotowywałem dewelopera, który był nowy w projekcie. Zamiast przeprowadzać go przez sekwencję konfiguracji, udostępniłem mu skrypt, i był gotowy do pracy w mniej niż minutę.
Błędy stały się również łatwiejsze do zdiagnozowania. Przed skryptem, zapomniane polecenie pip install pojawiało się jako ModuleNotFoundError głęboko w kodzie, co sprawiało, że spędzałem trochę czasu na debugowaniu. Teraz, jeśli instalacja zawiedzie, skrypt zatrzymuje się natychmiast i dokładnie wyświetla, co poszło nie tak.
Najmniejsza automatyzacja jest często najbardziej wartościowa
Twój skrypt nie musi być imponującym dziełem inżynierii, musi po prostu ułatwiać twoją pracę. Jeśli codziennie wykonujesz jakąkolwiek sekwencję poleceń, to jej automatyzacja z pewnością jest warta stworzenia.








