[Python] Erstellen Sie eine Stapelumgebung mit AWS-CDK

1. Zuallererst

Dieses Mal werden wir die AWS Batch-Umgebung mit CDK implementieren. Es gibt viele Beispiele für die Implementierung in TypeScript, aber es gab nicht viele in Python, deshalb habe ich einen Artikel geschrieben.

1.1 Ausführungsumgebung

Die Ausführungsumgebung ist wie folgt. Insbesondere werde ich nicht auf die Installation und die Grundeinstellungen von aws-cli und aws-cdk eingehen. Als Einschränkung hat aws-cdk jedoch eine sehr hohe Aktualisierungshäufigkeit für Versionen, und selbst die aktuell geschriebenen Inhalte funktionieren möglicherweise nicht.

1,2 Gebühr

Was besorgniserregend ist, ist der Preis. Als ich es unter den folgenden Bedingungen bewegte, wurde mir nur die EC2-Gebühr berechnet, die ungefähr 0,01 [$ / Tag] betrug. (In Batch wird die Instanz jedes Mal erstellt, nachdem die Warteschlange zum Job hinzugefügt wurde, und sie wird gelöscht, wenn der Job abgeschlossen ist.)

1.3 Vorgehensweise

Führen Sie die folgenden Schritte aus, um die Stapelausführungsumgebung vorzubereiten.

  1. Erstellen eines Python-Skripts
  2. Erstellen einer Docker-Datei
  3. Registrieren Sie sich bei ECR
  4. App in CDK schreiben

1.4 Vorbereitung

Die Ordnerstruktur ist wie folgt. Die Nummer auf der rechten Seite des Dateinamens entspricht der Nummer im obigen Verfahren.

batch_example
└── src
    ├── docker
    │   ├── __init__.py (1)
    │   ├── Dockerfile (2)
    │   ├── requirements.txt (2)
    │   └── Makefile (3)
    └── batch_environment
        ├── app.py (4)
        ├── cdk.json
        └── README.md

2. Implementierung

Fahren wir nun mit der Implementierung gemäß dem obigen Verfahren fort.

2.1 Erstellen eines Python-Skripts

Ein Beispiel für ein Skript, das in Docker ausgeführt werden soll, ist unten dargestellt. click dient zum Übergeben von Befehlszeilenargumenten von CMD Wachturm wird verwendet, um Protokolle in CloudWatch-Protokolle zu schreiben.

__init__.py


#Zur Zeitanalyse
from datetime import datetime
from logging import getLogger, INFO
#Installationsbibliothek
from boto3.session import Session
import click
import watchtower


#Ruft den Wert aus der Umgebungsvariablen ab, wenn er mit envvar angegeben wird
@click.command()
@click.option("--time")
@click.option("--s3_bucket", envvar='S3_BUCKET')
def main(time: str, s3_bucket: str):
    if time:
        #Analysezeit unter der Annahme der Ausführung vom CloudWatch-Ereignis
        d = datetime.strptime(time, "%Y-%m-%dT%H:%M:%SZ")
        #Ausführungsdatum abrufen
        execute_date = d.strftime("%Y-%m-%d")

    #Logger-Einstellungen
    #Der Name des Loggers wird zum Namen des Log-Streams
    logger_name = f"{datetime.now().strftime('%Y/%m/%d')}"
    logger = getLogger(logger_name)
    logger.setLevel(INFO)
    #Geben Sie hier den Namen der CloudWatch-Protokollprotokollgruppe an
    #Übergeben Sie die Sitzung und senden Sie das Protokoll über die IAM-Rolle
    handler = watchtower.CloudWatchLogHandler(log_group="/aws/some_project", boto3_session=Session())
    logger.addHandler(handler)

    #Geplante Verarbeitung
    #Schreiben Sie hier nur das Ausführungsdatum und die Ausführungszeit in CloudWatch-Protokolle
    logger.info(f"{execute_date=}")
    
if __name__ == "__main__":
    """
    python __init__.py 
        --time 2020-09-11T12:30:00Z
        --s3_bucket your-bucket-here
    """
    main()

2.2 Erstellen einer Docker-Datei

Erstellen Sie als Nächstes eine Docker-Datei, die das obige Python-Skript ausführt. Ich habe es in mehreren Schritten unter Bezugnahme auf [hier] erstellt (https://future-architect.github.io/articles/20200513/).

Dockerfile


#Dies ist ein Container zum Bauen
FROM python:3.8-buster as builder

WORKDIR /opt/app

COPY requirements.txt /opt/app
RUN pip3 install -r requirements.txt

#Bereiten Sie von hier aus den Ausführungscontainer vor
FROM python:3.8-slim-buster as runner

COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
COPY src /opt/app/src

WORKDIR /opt/app/src
CMD ["python3", "__init__.py"]

Fügen Sie gleichzeitig die Bibliothek ein, die in der Datei require.txt verwendet werden soll.

requirements.txt


click
watchtower

2.3 Registrierung bei ECR

Registrieren Sie die Docker-Datei nach dem Erstellen in ECR. Erstellen Sie zunächst ein Repository, indem Sie auf der ECR in der Konsole auf die Schaltfläche "Repository erstellen" klicken.

スクリーンショット 2020-09-27 22.47.35.png

Stellen Sie den Namen des Repositorys entsprechend ein.

スクリーンショット 2020-09-27 22.49.17.png

Wählen Sie das erstellte Repository aus und klicken Sie auf die Schaltfläche "Push-Befehl anzeigen".

スクリーンショット 2020-09-27 22.50.23.png

Dann werden die zum Drücken erforderlichen Befehle angezeigt, also ** kopieren und ohne nachzudenken ausführen. ** ** ** Wenn Sie hier versagen, funktionieren die AWS CLI-Einstellungen meiner Meinung nach nicht ordnungsgemäß. Überprüfen Sie daher die AWS CLI-Einstellungen.

スクリーンショット 2020-09-27 22.51.53.png

Es ist schwierig, den Befehl jedes Mal einzugeben. Erstellen Sie daher ein Makefile, das eine Kopie des obigen Befehls ist. (Der Befehl "--username AWS" in 1 scheint eine Konstante zu sein.)

Makefile


.PHONY: help
help:
	@echo " == push docker image to ECR == "
	@echo "type 'make build tag push' to push docker image to ECR"
	@echo ""

.PHONY: login
login:
	(1 Befehl)aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {ACCOUNT_NUMBER}.dkr.ecr.ap-northeast-1.amazonaws.com

.PHONY: build
build:
	(2 Befehle)docker build -t {REPOSITORY_NAME} .

.PHONY: tag
tag:
	(3 Befehle)docker tag {REPOSITORY_NAME}:latest {ACCOUNT_NUMBER}.dkr.ecr.ap-northeast-1.amazonaws.com/{REPOSITORY_NAME}:latest

.PHONY: push
push:
	(4 Befehle)docker push {ACCOUNT_NUMBER}.dkr.ecr.ap-northeast-1.amazonaws.com/{REPOSITORY_NAME}:latest

Mit diesem Makefile können Sie den Befehl wie folgt leicht verkürzen. Darüber hinaus glaube ich nicht, dass das obige Makefile gefährliche Informationen enthält, selbst wenn es nach außen gelangt, sodass Sie den Quellcode freigeben können.

#Melden Sie sich bei ECR an
$ make login

#Schieben Sie das neueste Bild auf ECR
$ make build tag push

2.4 CDK-Implementierung

Der Implementierungsinhalt von CDK basiert auf diesem Artikel, der in TypeScript geschrieben wurde. Außerdem ist es besser, "$ cdk in it" in dem Verzeichnis auszuführen, in dem app.py im Voraus implementiert ist.

2.4.1 Installieren der für die Implementierung erforderlichen Pakete

Jeder Paketname ist lang ... Außerdem ist die Installationszeit ziemlich lang.

$ pip install aws-cdk-core aws-cdk-aws-stepfunctions aws-cdk-aws-stepfunctions-tasks aws-cdk-aws-events-targets aws-cdk.aws-ec2 aws-cdk.aws-batch aws-cdk.aws-ecr

2.4.2 Implementierung von app.py.

Erstellen Sie zunächst eine Klasse für die diesmal zu erstellende Umgebung. Stack_name und stack_env werden als Argumente der BatchEnvironment-Klasse festgelegt. Dies entspricht dem Namen dieser Umgebung und der Ausführungsumgebung (Verifikation / Entwicklung / Produktion). (Wenn Sie die Ausführungsumgebung wirklich trennen möchten, müssen Sie meines Erachtens auch das ECR-Repository ändern.)

app.py


from aws_cdk import (
    core,
    aws_ec2,
    aws_batch,
    aws_ecr,
    aws_ecs,
    aws_iam,
    aws_stepfunctions as aws_sfn,
    aws_stepfunctions_tasks as aws_sfn_tasks,
    aws_events,
    aws_events_targets,
)


class BatchEnvironment(core.Stack):
    """
Stapelumgebung und Schrittfunktionen, um sie auszuführen+Erstellen Sie eine CloudWatch-Ereignisumgebung

    """
    #Der oben erstellte ECR-Repository-Name
    #Ziehen Sie Bilder aus diesem Repository, wenn Sie in Batch ausgeführt werden
    ECR_REPOSITORY_ARN = "arn:aws:ecr:ap-northeast-1:{ACCOUNT_NUMBER}:repository/{YOUR_REPOSITORY_NAME}"

    def __init__(self, app: core.App, stack_name: str, stack_env: str):
        super().__init__(scope=app, id=f"{stack_name}-{stack_env}")
        #Die folgende Implementierung ist das Bild unten hier.

2.4.3 Implementierung von app.py (Erstellung einer VPC-Umgebung)

app.py


        # def __init__(...):im

        #CIDR liegt in dem Bereich, den Sie mögen
        cidr = "192.168.0.0/24"

        # === #
        # vpc #
        # === #
        #VPC ist (sollte) kostenlos verfügbar, wenn Sie nur das öffentliche Subnetz verwenden
        vpc = aws_ec2.Vpc(
            self,
            id=f"{stack_name}-{stack_env}-vpc",
            cidr=cidr,
            subnet_configuration=[
                #Definieren Sie die Netzmaske für das öffentliche Subnetz
                aws_ec2.SubnetConfiguration(
                    cidr_mask=28,
                    name=f"{stack_name}-{stack_env}-public",
                    subnet_type=aws_ec2.SubnetType.PUBLIC,
                )
            ],
        )

        security_group = aws_ec2.SecurityGroup(
            self,
            id=f'security-group-for-{stack_name}-{stack_env}',
            vpc=vpc,
            security_group_name=f'security-group-for-{stack_name}-{stack_env}',
            allow_all_outbound=True
        )

        batch_role = aws_iam.Role(
            scope=self,
            id=f"batch_role_for_{stack_name}-{stack_env}",
            role_name=f"batch_role_for_{stack_name}-{stack_env}",
            assumed_by=aws_iam.ServicePrincipal("batch.amazonaws.com")
        )

        batch_role.add_managed_policy(
            aws_iam.ManagedPolicy.from_managed_policy_arn(
                scope=self,
                id=f"AWSBatchServiceRole-{stack_env}",
                managed_policy_arn="arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole"
            )
        )

        batch_role.add_to_policy(
            aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                resources=[
                    "arn:aws:logs:*:*:*"
                ],
                actions=[
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents",
                    "logs:DescribeLogStreams"
                ]
            )
        )

        #Rolle für EC2
        instance_role = aws_iam.Role(
            scope=self,
            id=f"instance_role_for_{stack_name}-{stack_env}",
            role_name=f"instance_role_for_{stack_name}-{stack_env}",
            assumed_by=aws_iam.ServicePrincipal("ec2.amazonaws.com")
        )

        instance_role.add_managed_policy(
            aws_iam.ManagedPolicy.from_managed_policy_arn(
                scope=self,
                id=f"AmazonEC2ContainerServiceforEC2Role-{stack_env}",
                managed_policy_arn="arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
            )
        )

        #Richtlinie hinzufügen, um auf S3 zuzugreifen
        instance_role.add_to_policy(
            aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                resources=["*"],
                actions=["s3:*"]
            )
        )

        #Fügen Sie eine Richtlinie für den Zugriff auf CloudWatch-Protokolle hinzu
        instance_role.add_to_policy(
            aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                resources=[
                    "arn:aws:logs:*:*:*"
                ],
                actions=[
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents",
                    "logs:DescribeLogStreams"
                ]
            )
        )

        #Gewähren Sie EC2 eine Rolle
        instance_profile = aws_iam.CfnInstanceProfile(
            scope=self,
            id=f"instance_profile_for_{stack_name}-{stack_env}",
            instance_profile_name=f"instance_profile_for_{stack_name}-{stack_env}",
            roles=[instance_role.role_name]
        )

2.4.4 Implementierung von app.py (Stapelausführungsumgebung, Jobdefinition, Erstellung der Jobwarteschlange)

app.py


        #Fortsetzung der VPC...

        # ===== #
        # batch #
        # ===== #
        batch_compute_resources = aws_batch.ComputeResources(
            vpc=vpc,
            maxv_cpus=4,
            minv_cpus=0,
            security_groups=[security_group],
            instance_role=instance_profile.attr_arn,
            type=aws_batch.ComputeResourceType.SPOT
        )

        batch_compute_environment = aws_batch.ComputeEnvironment(
            scope=self,
            id=f"ProjectEnvironment-{stack_env}",
            compute_environment_name=f"ProjectEnvironmentBatch-{stack_env}",
            compute_resources=batch_compute_resources,
            service_role=batch_role
        )

        job_role = aws_iam.Role(
            scope=self,
            id=f"job_role_{stack_name}-{stack_env}",
            role_name=f"job_role_{stack_name}-{stack_env}",
            assumed_by=aws_iam.ServicePrincipal("ecs-tasks.amazonaws.com")
        )

        job_role.add_managed_policy(
            aws_iam.ManagedPolicy.from_managed_policy_arn(
                scope=self,
                id=f"AmazonECSTaskExecutionRolePolicy_{stack_name}-{stack_env}",
                managed_policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"

            )
        )

        job_role.add_managed_policy(
            aws_iam.ManagedPolicy.from_managed_policy_arn(
                scope=self,
                id=f"AmazonS3FullAccess_{stack_name}-{stack_env}",
                managed_policy_arn="arn:aws:iam::aws:policy/AmazonS3FullAccess"

            )
        )

        job_role.add_managed_policy(
            aws_iam.ManagedPolicy.from_managed_policy_arn(
                scope=self,
                id=f"CloudWatchLogsFullAccess_{stack_name}-{stack_env}",
                managed_policy_arn="arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
            )
        )

        batch_job_queue = aws_batch.JobQueue(
            scope=self,
            id=f"job_queue_for_{stack_name}-{stack_env}",
            job_queue_name=f"job_queue_for_{stack_name}-{stack_env}",
            compute_environments=[
                aws_batch.JobQueueComputeEnvironment(
                    compute_environment=batch_compute_environment,
                    order=1
                )
            ],
            priority=1
        )

        #Holen Sie sich das ECR-Repository
        ecr_repository = aws_ecr.Repository.from_repository_arn(
            scope=self,
            id=f"image_for_{stack_name}-{stack_env}",
            repository_arn=self.ECR_REPOSITORY_ARN
        )

        #Holen Sie sich ein Bild von ECR
        container_image = aws_ecs.ContainerImage.from_ecr_repository(
            repository=ecr_repository
        )

        #Jobdefinition
        #Verwenden Sie es hier im Python-Skript`S3_BUCKET`Als Umgebungsvariable
        batch_job_definition = aws_batch.JobDefinition(
            scope=self,
            id=f"job_definition_for_{stack_env}",
            job_definition_name=f"job_definition_for_{stack_env}",
            container=aws_batch.JobDefinitionContainer(
                image=container_image,
                environment={
                    "S3_BUCKET": f"{YOUR_S3_BUCKET}"
                },
                job_role=job_role,
                vcpus=1,
                memory_limit_mib=1024
            )
        )


2.4.5 Implementierung von app.py (Create StepFunctions + CloudWatch Events)

Von hier aus ist es nicht immer notwendig, die Batch-Umgebung zu erstellen. Dies erfolgt mithilfe von Schrittfunktionen und CloudWatch-Ereignis für die regelmäßige Ausführung.

Sie können Batch auch direkt vom CloudWatch-Ereignis aus aufrufen. Zwischen ihnen sind Schrittfunktionen angeordnet, um die Zusammenarbeit mit anderen Diensten und die Übergabe von Parametern zu vereinfachen.

Bei der Registrierung als Schritt Funktionen Schritt Überschreiben Sie den Docker CMD-Befehl (= in der Jobdefinition von Batch festgelegt) und Es nimmt das Argument "Zeit" aus dem CloudWatch-Ereignis und übergibt es an das Python-Skript.

app.py


        #Fortsetzung von Batch...

        # ============= #
        # StepFunctions #
        # ============= #

        command_overrides = [
            "python", "__init__.py",
            "--time", "Ref::time"
        ]

        batch_task = aws_sfn_tasks.BatchSubmitJob(
            scope=self,
            id=f"batch_job_{stack_env}",
            job_definition=batch_job_definition,
            job_name=f"batch_job_{stack_env}_today",
            job_queue=batch_job_queue,
            container_overrides=aws_sfn_tasks.BatchContainerOverrides(
                command=command_overrides
            ),
            payload=aws_sfn.TaskInput.from_object(
                {
                    "time.$": "$.time"
                }
            )
        )

        #Dieses Mal gibt es nur einen Schritt, es ist also einfach, aber wenn Sie mehrere Schritte verbinden möchten
        # batch_task.next(aws_sfn_tasks.JOB).next(aws_sfn_tasks.JOB)
        #Sie können es mit der Kettenmethode wie übergeben.
        definition = batch_task

        sfn_daily_process = aws_sfn.StateMachine(
            scope=self,
            id=f"YourProjectSFn-{stack_env}",
            definition=definition
        )

        # ================ #
        # CloudWatch Event #
        # ================ #

        # Run every day at 21:30 JST
        # See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html
        events_daily_process = aws_events.Rule(
            scope=self,
            id=f"DailySFnProcess-{stack_env}",
            schedule=aws_events.Schedule.cron(
                minute=31,
                hour=12,
                month='*',
                day="*",
                year='*'),
        )
        events_daily_process.add_target(aws_events_targets.SfnStateMachine(sfn_daily_process))

        #Bis hierher def__init__(...):

2.4.6 Implementierung von app.py (Implementierung der Hauptfunktion)

Schreiben Sie abschließend den Prozess zum Ausführen des CDK und Sie sind fertig.

app.py


#Hier def__init__(...):


def main():
    app = core.App()
    BatchEnvironment(app, "your-project", "feature")
    BatchEnvironment(app, "your-project", "dev")
    BatchEnvironment(app, "your-project", "prod")
    app.synth()


if __name__ == "__main__":
    main()

2.5 Bereitstellen

Überprüfen Sie nach Abschluss des obigen Skripts mit dem folgenden Befehl, ob das CDK richtig eingestellt ist, und stellen Sie es dann bereit. Selbst wenn Sie eine Batch-Umgebung von Grund auf neu erstellen, ist diese in etwa 10 Minuten abgeschlossen.

#Bestätigung der Definition
$ cdk synth

Successfully synthesized to {path_your_project}/cdk.out
Supply a stack id (your-project-dev, your-project-feature, your-project-prod) to display its template.

#Bestätigung der bereitstellbaren Umgebung
$ cdk ls

your-project-dev
your-project-feature
your-project-prod

$ cdk deploy your-project-feature

...deploying...

2.5.1 Überprüfen Sie, ob die Umgebung korrekt erstellt wurde

Wenn die Bereitstellung abgeschlossen ist, wählen Sie die von Ihnen in der Konsole erstellten Schrittfunktionen aus und klicken Sie auf die Schaltfläche "Ausführung starten".

スクリーンショット 2020-09-27 23.38.58.png

Setzen Sie nur das Argument der "Zeit",

{
    "time": "2020-09-27T12:31:00Z"
}

スクリーンショット 2020-09-27 23.45.12.png

Wenn es richtig funktioniert, sind Sie fertig. Überprüfen Sie außerdem die CloudWatch-Protokolle, um festzustellen, ob sie wie erwartet funktionieren.

3. Fazit

Ich mag CDK wirklich, weil Sie die Umgebung mit Befehlen schnell erstellen und löschen können!

Anstatt über die Konsole zu erstellen, können Sie auch sehen, was für die Programmparameter erforderlich ist Auch wenn Sie den Service nicht kennen, dachte ich, es wäre schön zu wissen, welche Parameter erforderlich sind!

(Eines Tages werde ich die obige Quelle im GitHub-Repository erweitern ...!)

Recommended Posts

[Python] Erstellen Sie eine Stapelumgebung mit AWS-CDK
Erstellen Sie eine Python-Umgebung
Erstellen Sie mit tkinter eine Python-GUI
Erstellen Sie eine Python-Umgebung auf dem Mac (2017/4)
Erstellen Sie eine virtuelle Umgebung mit Python!
Erstellen Sie eine Python-Umgebung in Centos
Erstellen Sie eine Python-Umgebung auf Ihrem Mac
Erstellen wir eine virtuelle Umgebung für Python
Erstellen Sie einen einfachen geplanten Stapel mit Dockers Python Image und parse-crontab
Erstellen Sie in 1 Minute eine Vim + Python-Testumgebung
Erstellen Sie eine GIF-Datei mit Pillow in Python
Erstellen Sie eine virtuelle Umgebung mit conda in Python
Erstellen Sie mit Sublime Text3 eine Python3-Build-Umgebung
Erstellen Sie eine Webmap mit Python und GDAL
[Venv] Erstellen Sie eine virtuelle Python-Umgebung unter Ubuntu
Erstellen Sie eine MIDI-Datei in Python mit pretty_midi
Erstellen Sie eine Python-Ausführungsumgebung unter IBM i
[Docker] Erstellen Sie in 3 Minuten eine jupyterLab (Python) -Umgebung!
Erstellen Sie mit Selenium einen Datenerfassungsbot in Python
Erstellen Sie ein Wox-Plugin (Python)
Erstellen Sie eine Funktion in Python
Erstellen Sie ein Wörterbuch in Python
So richten Sie eine Python-Umgebung mit pyenv ein
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 1 ~
[Python] Generieren Sie ValueObject mit dem vollständigen Konstruktor mithilfe von Datenklassen
Erstellen Sie eine komfortable Python 3 (Anaconda) -Entwicklungsumgebung mit Windows
Erstellen Sie eine Python-Entwicklungsumgebung mit Vagrant + Ansible + Fabric
Erstellen Sie JIRA-Tickets mit Python
Erstellen Sie eine virtuelle Python-Umgebung mit venv (Django + MySQL ①)
Erstellen einer virtuellen Python-Umgebung
Erstellen Sie mit pyenv eine Python-Umgebung auf Ihrem Mac
Erstellen Sie ein Python-Numpy-Array
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 2 ~
Erstellen Sie eine Python-Entwicklungsumgebung mit pyenv unter MacOS
Erstellen Sie die Python-Umgebung offline
Erstellen Sie ein Verzeichnis mit Python
Erstellen Sie unter Windows eine anständige Shell- und Python-Umgebung
Erstellen einer virtuellen Python-Umgebung
Konstruktionsnotiz für eine maschinelle Lernumgebung von Python
Erstellen Sie eine Python-Entwicklungsumgebung mit OS X Lion
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 3 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 4 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 5 ~
Erstellen Sie eine Python-Entwicklungsumgebung (pyenv / virtualenv) auf einem Mac (Homebrew).
Erstellen einer Python-Umgebung auf einem Mac bis zur Verwendung von Jupyter Lab
Erstellen Sie mit VSCode & Docker Desktop eine einfache Python-Entwicklungsumgebung
Erstellen einer virtuellen Umgebung für Python auf dem Mac [Sehr einfach]
Erstellen einer Python-Umgebung auf einem Mac
Ich habe einen Line-Bot mit Python gemacht!
Erstellen Sie einen DI-Container mit Python
Erstellen einer Python-Umgebung unter Ubuntu
Zeichnen einer Silbersteinkurve mit Python
Erstellen Sie ein verschachteltes Wörterbuch mit defaultdict
Erstellen Sie eine Binärdatei in Python
Erstellen einer virtuellen Umgebung mit Python 3
Erstellen Sie eine Linux-Umgebung unter Windows 10
Erstellen Sie ein universelles Dekorationsframework für Python