Python ve FTP Dosya İşlemleri
Request, os ve ftp paket kullanım örneği
Son yayınladığım Veri Ambarı (Data Warehouse) Nedir? başlıklı yazıdan bu yana tam 50 gün geçmiş. Yazıların seyrekleşmesi ve yeni yazı frekansının düşmesi ile ilgili pek çok nedeni var elbette.
2021 Hedefleri başlıklı yazıda da belirttiğim üzere bu yıl ağırlıklı olarak eğitimleri önceliklendirmiş olmam. Önümüzdeki zaman içerisinde bu konuya dair paylaşımlarım olacak. Bu paylaşımlardan ilki olarak, bir Python örneğine değinmek istiyorum.
Python İle Basit Request ve FTP İşlemi
Grav Yeni Tema ve Peformans Değişimi başlıklı yazıda, şu anda görüntülemekte olduğunuz bu tema ile ilgili olarak Parsedown ve Parsedown Extra dosyalarında çeşitli özelleştirmeler yapmıştım. Ancak, her yeni Grav sürümünde maalesef bu değişiklikler kaybolduğu için (dosya yedekleri ile süreci yönetiyordum) tekrar tekrar bazı işlemleri yapmak durumunda kalıyordum. Sistem dosyaları Git reposu dışında kaldığı için işlemleri SSH veya FTP üzerinden bağlantı kurarak yönetmek gerekiyordu.
Grav üzerinden ilgili class
'ı extend
ederek işlemler yapmak mümkün görünüyor. Ancak, daha net bir çözüm sağlayamadım. Geçici bir çözüm arayışı içerisinde, şu sıralar öğrenmek için yoğun bir şekilde vakit ayırdığım Python ile örneklendirme fikri geldi.
Parsedown1 ve Parsedown Extra2 için 2 ayrı gist üzeriden yaptığım değişiklikleri benzer değişiklikleri yapma ihtiyacı duyanlar için paylaşmıştım. Dolayısıyla, sürece yine bu gist'leri dahil edeceğim. Ek olarak, süreci sadece bu 2 dosya ile tutmak istemiyorum. Bu nedenle, doğrudan dosya tanımlamak yerine içeriği dict
olarak iletmeye karar verdim.
from ftplib import FTP
import os
import requests
class ParsedownFTPSyc:
def __init__(self, FTP, GIST, CHUNKSIZE=100):
self.FTP = FTP
self.GIST = GIST
self.CHUNKSIZE = CHUNKSIZE
def createLocalDir(self, whr):
if os.path.exists(whr) is False:
os.mkdir(whr)
os.chdir(whr)
def getGists(self, whr='/private/tmp/parsedown/'):
self.createLocalDir(whr)
for dirs in self.GIST['files'].items():
currGist = dirs[1]
gistURL = f'%s/%s/%s' % (self.GIST['user'],
currGist['gistid'],
currGist['file'])
try:
req = requests.get(gistURL, allow_redirects=True)
except Exception as err:
print(err)
else:
if req.status_code == 200:
with open(currGist['file'], 'wb') as fd:
for chunk in req.iter_content(self.CHUNKSIZE):
fd.write(chunk)
print('%s is OK' % currGist['file'])
def writeFTPFile(self, frm):
try:
with FTP(self.FTP['host']) as ftp:
ftp.login(user=self.FTP['user'], passwd=self.FTP['pass'])
ftp.cwd(self.FTP['dirn'])
for dirs in self.GIST['files'].items():
FILE = dirs[1]['file']
ftp.cwd(self.FTP['dirn'] + dirs[0])
with open(frm + FILE, 'rb') as f:
ftp.storlines(f"STOR {FILE}", f)
ftp.quit()
except Exception as err:
print(err)
def main():
newSync = ParsedownFTPSyc(
FTP={
'host': 'ftp.domain.com',
'user': 'user@domain.com',
'pass': 'password123',
'dirn': "/app/",
},
GIST={
'user': 'https://gist.githubusercontent.com/ceaksan',
'files': {
'parsedown': {
'gistid': '194ff03625f6050dc2959ec062b0c68a/raw/c2be5d72237a46f56692ae17716c0e9739070fb7',
'file': 'Parsedown.php'
},
'parsedown-extra': {
'gistid': '99d17f8d6691f8948f701468e6611a34/raw/cfc87d141d258838576635105b7ebc277e4affa8',
'file': 'ParsedownExtra.php'
}
}
})
newSync.getGists(whr='/private/tmp/parsedown/')
newSync.writeFTPFile(frm='/private/tmp/parsedown/')
if __name__ == '__main__':
main()
Evet, görüldüğü üzere bir de FTP paketi kullanılmakta. Kod parçacığının yaptığı iş öncelikle GIST
içerisinde belirtilen kullanıcı tarafından paylaşılmış olan gist'leri lokal ortamda, belirtilen dizine indirmek.
Ardından, indirilen bu dosyaları FTP
içerisinde belirtilen adrese yüklemek. dirn
elbette gist özelinde de belirtilebilir. Ancak, örnekteki 2 dosya aynı dizin altında yer aldığı için örnekte tek bir property değeri üzerinden ilerledim.
Son olarak, bu konu pratik bir şekilde nasıl çalıştırabileceğimize bakalım.
Elbette python
, ipython
veya jupyter
başta olmak üzere pek çok ortam aracılığı ile işlem gerçekleştirmek mümkün. Ancak, doğrudan bir dosya tıklaması ya da komut satırı ifadesi ile de ilerlenebilir.
Yukarıdaki kod parçacığının ilk satırına #!/usr/bin/env python3
eklemesini yaptığınızda ilgili kod artık ./dosya-adi.py
şeklinde de çalıştırılabilir. python3
yerine kullanılan sürüm yazılabilir.
#!/usr/bin/env python3
from ftplib import FTP
import os
import requests
...
Bunun yanı sıra, bir shell script dosyası aracılığı ile de kod parçacığının işleme alınması sağlanabilir.
#!/bin/sh
python3 dosya-adi.py
Seçilen yöntem hangisi olduğu fark etmeksizin komut satırı için bir alias oluşturabiliriz. Bunun için şu adımları izlemek yeterli olacaktır.
chmod +x dosya-adi.py
alias parsedown="/dosya-dizini/dosya-adi.py" # ya da .sh dosya yolu
source ~/.zshrc
Evet, bu işlemle birlike artık komut satırına parsedown
yazmamız durumunda ilgili dosyalara ait gist'ler indirilecek ve FTP aracılığı ile belirtilen dizine yüklenecektir.
İlerleyen zaman içerisinde Python ile ilgili edindiğim yeni bilgiler doğrultusunda bu kod parçacığını güncellemeye devam edeceğim. Kod ile ilgili önerileriniz olursa değerlendirmekten memnuniyet duyarım.