Seite 2 von 2

Re: PHP zu Python: Optimierung eines vorhanden Scripts

Verfasst: Mittwoch 15. Januar 2025, 11:55
von grubenfox
__blackjack__ hat geschrieben: Mittwoch 15. Januar 2025, 10:50 @mmueller-87: Wobei man auch bei FTP bei Python bleiben könnte — gibt ja `ftplib` in der Standardbibliothek.

@grubenfox: Auf den ersten Blick sieht `pyftplib` nach einem *Server* aus. Kann das auch Client? Denn das wird ja gebraucht.
@__blackjack__: keinen blassen Schimmer. War der erste Treffer mit etwas zu "throttle-bandwidth". Dazu hatte ich bei `ftplib` aus der Standardbibliothek auf die Schnelle nichts gefunden.

P.S: Ja, da war ich wohl falshc... `pyftplib` ist offenbar nur Server.

Re: PHP zu Python: Optimierung eines vorhanden Scripts

Verfasst: Mittwoch 15. Januar 2025, 17:38
von mmueller-87
grubenfox hat geschrieben: Mittwoch 15. Januar 2025, 10:44
mmueller-87 hat geschrieben: Mittwoch 15. Januar 2025, 10:14 Nun würde ich gerne, wenn das Python Script die Dateien hochlädt, das es eine Bandbreitenbegrenzung gibt, und "ncftp" die Dateien statt mit 3 MBits nur mit 100kBits höchlädt. Wäre das umsetzbar?
[ungetestet]
Das "Subprocess" rauswerfen (inkl. ncftp) und

Code: Alles auswählen

import pyftplib
einfügen und dort dann mit throttle-bandwidth arbeiten.

Ok, Vielen Dank, habe mich etwas eingelesen und probiere verschiedenes aus, diese Funktion funktioniert, aber mir fehlt ein bisschen das "Error handling" um zu prüfen ob die Datei hochgeladen wurde, oder der Server nicht erreichbar ist. Kann mir jemand beim anpassen helfen. Hier ein Snippet der Funktion:

Code: Alles auswählen

def ftp_upload(local_file, media_type):
    # Connect FTP Server
    ftp_server = ftplib.FTP(FTP_HOSTNAME, FTP_USERNAME, FTP_PASSWORD)
    ftp_server.encoding = "utf-8"

    # Get list of files
    # ftp_server.dir()
    # audios: /cache/receiver_b/audio/
    # thumbs: /templates/default/m3images/
    # images: /templates/default/m3images/

    # Read file in binary mode
    with open(local_file, "rb") as file:
        # Media directory
        if media_type == "audio":
            media_folder = "/cache/receiver_b/audio/"
        else:
            media_folder = "/templates/default/m3images/"

        # Command for uploading
        ftp_server.storbinary(f"STOR {media_folder}{local_file}", file)

    # Close the Connection
    ftp_server.quit()

Re: PHP zu Python: Optimierung eines vorhanden Scripts

Verfasst: Freitag 17. Januar 2025, 12:06
von __blackjack__
@mmueller-87: Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.

Bei `file` im Namen würde man ein Datei-Objekt erwarten und keine Zeichenkette mit einem Dateinamen.

Die Kodierung kann man einem `FTP`-Objekt schon beim erstellen mitgeben. Das UTF-8 aber schon die Voreinstellung ist, braucht man das hier nicht.

`FTP`-Objekte sind Kontextmanager, die sollte man mit ``with`` verwenden.

Zwischenstand (ungetestet):

Code: Alles auswählen

def ftp_upload(local_filename, media_type):
    with ftplib.FTP(FTP_HOSTNAME, FTP_USERNAME, FTP_PASSWORD) as ftp_server:
        with open(local_filename, "rb") as file:
            #
            # audios: /cache/receiver_b/audio/
            # thumbs: /templates/default/m3images/
            # images: /templates/default/m3images/
            #
            media_folder = (
                "/cache/receiver_b/audio/"
                if media_type == "audio"
                else "/templates/default/m3images/"
            )
            ftp_server.storbinary(f"STOR {media_folder}{local_filename}", file)
Die Fehlerbehandlung würde ich ausserhalb dieser Funktion machen. Oder was könnte/sollte die sinnvolles tun wenn die Verbindung zum Server nicht funktioniert oder die Datei nicht übertragen werden kann?

Bandbreite könnte man übrigens über die optionale Rückruffunktion begrenzen, die man bei `storbinary()` angeben kann.

Re: PHP zu Python: Optimierung eines vorhanden Scripts

Verfasst: Samstag 21. Juni 2025, 23:50
von snafu
Bei der Bandbreitenbegrenzung könnte man sich etwas simples mit einer Klasse als Callback und Anpassung der Blockgröße basteln.

Beispiel für die genannten 100 kBit/s:

Code: Alles auswählen

import ftplib
from time import monotonic, sleep

BANDWIDTH = 100 * 1024

class Clock:
    def __init__(self, interval):
        self.interval = interval
        self._time = monotonic()

    def tick(self, *args):
        next_time = self._time + self.interval
        if (delay := next_time - monotonic()) > 0:
            sleep(delay)
        self._time = monotonic()


def ftp_upload(local_filename, media_type):
    with ftplib.FTP(FTP_HOSTNAME, FTP_USERNAME, FTP_PASSWORD) as ftp_server:
        with open(local_filename, "rb") as file:
            #
            # audios: /cache/receiver_b/audio/
            # thumbs: /templates/default/m3images/
            # images: /templates/default/m3images/
            #
            media_folder = (
                "/cache/receiver_b/audio/"
                if media_type == "audio"
                else "/templates/default/m3images/"
            )
            ftp_server.storbinary(
                f"STOR {media_folder}{local_filename}", file,
                BANDWIDTH // 10, Clock(0.1).tick
            )
Natürlich werden es bei höheren Bandbreiten irgendwann riesige Blockgrößen. Da müsste man den Ansatz entsprechend ausarbeiten. Aber für das Beispiel passte es ganz gut.

Re: PHP zu Python: Optimierung eines vorhanden Scripts

Verfasst: Montag 23. Juni 2025, 16:28
von snafu
Nachtrag: Da die Bandbreite in Bit, aber die Blockgröße in Byte angegeben wird, muss man die Bandbreite zusätzlich durch 8 teilen. Somit werden die Blöcke dann auch entsprechend kleiner.