May 31, 2020

İrdelemeler: WoeUSB ile Linux Üzerinde Önyüklenebilir Windows 10 USB Sürücüsü Oluşturma

WoeUSB, Linux’ta önyüklenebilir bir Windows 10 USB sürücüsü oluşturmak için kullanabileceğimiz kolay ve pratik bir uygulamadır.

WoeUSB ücretsiz, açık kaynaklı bir yazılımdır.Hem GUI(Graphical User Interface), hem de CLI(Command Line Install) olarak kullanılabilir. Bu yazıda GUI’ye odaklanıyoruz.Daha detalı bir kullanımı tercih edenler, WoeUSB CLI’ye göz atabilirler.

WoeUSB, Windows Vista, Windows 7, Windows 8 ve Windows 10 da dahil olmak üzere çoğu modern Windows sürümü için önyüklenebilir bir USB oluşturmanıza olanak tanırken, tüm dilleri ve Windows’un tüm sürümlerini destekler.Hem ‘Legacy’ hem de ‘UEFI’ önyükleme modlarıyla çalışır.

Bu yazıda önyüklenebilir bir Windows 10 USB sürücüsü oluşturacağız.

Linux’da önyüklenebilir bir Windows 10 USB sürücüsü oluşturmak için ihtiyaç duyulacak şeyler listesi:

*WoeUSB uygulaması

*USB flash sürücü (minimum 4 GB)

*Windows ISO dosyası

Microsoft, Windows 10 disk görüntülerini web sitesinden indirmenize izin verir, Eğer yoksa, bu şekilde bir tane edinebilirsiniz.İşletim sistemini etkinleştirmek için geçerli bir Windows lisansına ihtiyacınız olsa da, önyüklenebilir bir Windows 10 USB sürücüsü oluşturmak veya yüklemek için lisansa ihtiyaç yoktur.

Dağıtımla için WoeUSB kurmanın çeşitli yolları mevcuttur.WoeUSB GitHub sayfasından kurulumla ilgili bilgilere erişilebilir.Bu yazıda Arch Linux üzerinde WoeUSB kurarak anlatım yapacağız.

Arch Linux için WoeUSB depolardan kurulabilir durumdadır:

sudo pacman -S woeusb

WoeUSB kurulduktan sonra uygulamayı uygulamalar menüsünden başlatabilirsiniz.

Uygulamanın kullanımı çok kolaydır.

İlk olarak, dosya seçiciyi kullanarak geçerli bir Windows 10 ISO görüntüsü seçiyoruz.Ardından ‘Hedef aygıt’ bölümünden yüklemek istediğimiz USB sürücüsünü seçiyoruz.Windows 10 USB

USB cihazınızın ‘Hedef aygıt’ bölümünde listelendiğini göremiyorsanız, takılı olduğundan emin olun ve ardından bağlı cihazların listesini güncellemek için ‘Tazele’ düğmesini tıklayın.

Her şey hazır olduğunda, devam edip ‘Install’ diyoruz.(Eğer USB sürücüsü bağlı ise bu aşamada ayırmanız gerekecektir.)Kullanıcı şifrenizi isteyecektir, giriyoruz.Ancak bunu yapmadan önce doğru USB sürücüyü seçtiğinizden emin olmalısınız.Zira yükleme işlemi, seçilen USB sürücüyü yeniden biçimlendirecek ve içeriğini silecektir.Hatalı bir seçim yapmanız durumunda USB üzerinde depolanan tüm verileri kaybedebilirsiniz.

Her şey doğru yapıldıysa kurulum başlayacak ve bundan sonrasını araç kendisi halledecektir.

İşlem bittiğinde uygulamayı kapatabilir, USB’yi çıkarabilir ve Windows 10’u farklı bir cihaza yüklemek için kullanabilirsiniz.

May 25, 2020

Vps Server Disk Doluluk Kontrol Betiği

Lazım olmayınca kullanılmıyor tabiki.

Dün gerekli olduğunu farkettim.

iran kaynaklı Qmail eposta sunucusuna yapılan login denemelerinden sonra 400MB civarı log dosyası oluşmuş.

Sistem diski zaten küçük disk neredeyse 100% dolmuş.

sistem diski 95% doluluk oranına ulaşınca haber veren betik hazırladım.

Kullanırsanız ve olumslu veya olumsuz aşağıya yorum olarak bildirirseniz mutlu olurum.

 

#!/bin/bash
# caylakpenguen
# Paz 24 May 2020 17:18:38 +03 
# Disk Doluluk Kontrolu....
# Disk dolulugu belirli seviyeyi gectiginde
# ilgili kisiye bildirim gonderir.
#cron gorevi icin girdi. 15 dakikada bir calisir.
# */15 * * * * /opt/disk.sh

#Tarih
TARIH=$(date '+%F-%H-%M')
## Sistem Kok Bolumu
DISKADI="/dev/sda1"

## Kime Eposta Gonderilecek...
KIME="admin@local.lan"

#data dosyasi...
MAILFILE="/tmp/eposta.txt"
DISKUSE="/tmp/diskdf.txt"
# % de olarak hesaplanir.
SINIR="90"

kontrol(){

df -h | grep "$DISKADI" | awk '{ print $5}' > $DISKUSE

DURUM=$(cat $DISKUSE | cut -f1 -d\%)

if [ $DURUM -ge $SINIR ]; then
        echo "UYARI! Disk Kullanimi % $SINIR" > $MAILFILE
        echo "" >> $MAILFILE
        echo "Sistem Disk doluluk orani. % $DURUM " >> $MAILFILE
	echo "Sistem Diskinizi kontrol ediniz." >> $MAILFILE
        echo "" >> $MAILFILE
        echo "iyi calismalar..." >> $MAILFILE
	echo "$(hostname)" >> $MAILFILE
	echo "Tarih:  $TARIH ." >> $MAILFILE
        mail -s "UYARI! Disk Kullanimi 90%" $KIME < $MAILFILE
	rm -f $MAILFILE $DISKUSE
	
fi
}

#
kontrol

Faydalı olması dileğiyle.

 

 

 

May 24, 2020

Linux: VirtualBox’ta USB Sürücüsünden Önyükleme Yapma

Bu yazıda, Linux sistemde Ventoy ile çoklu önyüklenebilir USB sürücüsü oluşturmuştuk.Önyüklenebilir sürücüyü başarıyla oluşturduktan sonra, önyüklenebilir sürücüye farklı ISO’lar ekledik. Ancak sorun şu ki, USB sürücüsüne eklenen her yeni bir ISO’nun gerçekten çalışıp çalışmadığını kontrol etmek için, her eklemeden sonra sistemi yeniden başlatmak gerekiyor.Bunun için ikinci bir bilgisayar var, ancak her seferinde bilgisayarı kapat, yeniden başlat falan; zaman kaybı.Bu işlemi VirtualBox’ta yapabilmek daha pratik bir çözüm olacaktı.Lakin, VirtualBox, USB’den önyükleme yapmak için doğrudan bir yol sunmuyor.Ancak, Linux’ta çareler tükenmez!

USB sürücüsünden Virtualbox önyüklemesine izin vermek için, bir vmdk dosyası oluşturmak ve önyükleme yapmak için USB sürücüsünü yönlendirmek gerekiyor.

Merak edenler için bilgi: Bir vmdk dosyası, sanal makinenin tüm bilgilerini içeren bir sanal disk dosyasından başka bir şey değildir.

İlk olarak, USB sürücü adınızı bulmanız gerekir.Bunun için fdisk komutunu kullanacağız.

$ sudo fdisk -l

Komut şöyle bir çıktı döndürüyor:

[...]
Disk /dev/sdb: 14,43 GiB, 15483273216 bayt, 30240768 sektör
Disk model: DataTraveler 2.0
Birimler: sektör'i 1 * 512 = 512 baytın
Sektör boyutu (montıksal/fiziksel): 512 bayt / 512 bayt
G/Ç boyutu (en düşük/en uygun): 512 bayt / 512 bayt
Disketikeri tipi: dos
Disk belirleyicisi: 0x5e0caad7

Gördüğünüz gibi benim USB sürücü adım /dev/sdb.

Sanal Disk Dosyası Oluşturma

Şimdi, bir terminal(uçbirim) açıyoruz ve bir vmdk dosyası oluşturmak için aşağıdaki komutu çalştırıyoruz:

sudo vboxmanage internalcommands createrawvmdk -filename ~/usb.vmdk -rawdisk /dev/sdb

Bazı Linux dağıtımlarında vboxmanage komutu büyük/küçük harfe duyarlıdır. Bu durumda, aşağıdaki komutu kullanabiliriz:

sudo VBoxManage internalcommands createrawvmdk -filename ~/usb.vmdk -rawdisk /dev/sdb

Yukarıdaki komut, $HOME(Ev) dizininizde usb.vmdk adında yeni bir vmdk dosyası oluşturacaktır. vmdk dosyası oluşturulduktan sonra, aşağıdaki gibi bir çıktı görüntülenecek:

RAW host disk access VMDK file /home/kesim/usb.vmdk created successfully.

Yeni oluşturulan vmdk dosyası için uygun izin ayarlarını yapıyoruz:

sudo chown $USER:$USER ~/usb.vmdk

Ardından, aşağıdaki komutları kullanarak kullanıcı adımızı vboxusers ve disk gruplarına ekliyoruz:

sudo usermod -a -G vboxusers kesim
sudo usermod -a -G disk kesim

(Burada kesim benim kullanıcı adım.Siz kendiniz için oluştururken, kendi kullanıcı adınızı kullanacaksınız.)

Şimdi USB sürücüsünü çıkarıyoruz ve değişikliklerin etkili olması için sisteminizi yeniden başlatıyoruz. USB sürücüsünü çıkarmazsak, bir sonraki önyüklemede sürücünün adı değişebilir. Bu yüzden önce USB’yi çıkarmak ve ondan sonra sistemi yeniden başlatmak önemlidir.

VirtualBox’ta Usb Önyüklemeli Sanal Makine Oluşturma

VirtualBox’u açıyoruz ve yeni bir sanal makine oluşturuyoruz…

bu yazıda

Sitemimizi resimdeki gibi ayarlıyoruz…

Bellek boyutumuzu ayarlıyoruz…

Sabit disk ayarlamaları…Sanal disk seçimi için önce en alttaki kutucuğa, sonra da sağ taraftaki dosya simgesine tıklıyoruz…

Ekle diyoruz…

bu yazıda

Bu adımda, yukarıdaki anlatımla oluşturduğumuz vmdk dosyasını seçiyoruz…

Seçtik…

Sanal sabit diskimiz için son adımdayız.Oluştur diyoruz…

Şimdi artık, bu yazıda hazırlamış olduğumuz önyüklenebilir USB belleğimizden önyükleme yapabiliriz.

Ve sistemi Önyüklenebilir USB bellekten başlattık…Artık istediğimiz sistemi seçerek devam edebiliriz!

 

May 23, 2020

Pek bilinmeyen altı tane web browser

Bilindiği gibi, Debian Türkiye Forum’un değerli bir üyesi, değerli arkadaşımız Vedat Kılıç; uzun zamandır kendine özgü ISO kalıpları hazırlıyor. Vedat, bunları kendisine ait olan gnulinuxfree.blogspot.com üzerinden yayımlıyor. Bilindiği gibi, daha geniş bir çevreye duyurulması amacıyla bu çalışmaları forum üzerinden ve buradan da sizlere duyurmaya çaba gösteriyoruz. Vedat Kılıç‘ın en son yazdığı “Pek bilinmeyen altı tane web browser” adlı yazı, bu kez farklı, bir o kadar da ilginç bir konu içeriyor. Bu nedenle, bu yazıyı da sizlere aktarmak istedim. Dostumuz yazısına şöyle başlıyor: “GNU/Linux için yapılmış ama henüz dağıtım depolarına girmemiş 7 tane farklı web tarayıcıyı ile tanışacağız. Bu tarayıcıların kimisi muhtemelen zaman içinde depolara girecek, kimisi belki hiç giremeden durdurulacak, o kadarını bilemeyiz ama en azından yenilik adına onlara göz atmakta fayda var.

Sielo web browser

Resimde görülen tarayıcının adı Sielo, bir Fransız tarafından geliştirilmiş, Chromium tabanlı, bir kaç dile sahip, henüz Türkçe yok, AppImage paketi olarak paylaşılıyor. AppImage bütün bağımlılıkları kendi içinde olan, üzerine çift tıklamayla çalışan yeni tür kurulmadan çalışan portable paket prensibine dayanıyor. Kurulmadan ve USB’den çalışıyor olması bir çoklarının tercihi olsa da dosya içeriği görülmediği için temel geliştiricilerin bazıları tarafından şiddetle eleştiriliyor ve desteklenmiyor. Lakin konumuz bu olmadığı için burayı geçiyoruz. Dünyaya açılan pencere de denilen web browserler içinde Sielo browserin arayüzü dünyayı gezen pencereye benziyor. Neredeyse bütün tuşları istenen yere taşınabiliyor. Örneğin resimde görülen yuvarlak daire aslında yan panel ama hem yerini hem şeklini değiştirebiliyorsunuz. Bu panel imleci takip ediyor, imleç hangi sayfadaysa anında o sayfaya geçiyor. Resimde bir kısmı görüldüğü gibi sayısız sekmeleri ve sayfaları arayüze döşeyebiliyorsunuz, bunun için sekmeleri istediğiniz bölgeye sürüklemeniz yetiyor. Sielo browserde ayrıca bukelamun gibi her bölgesine, arkaplanına veya sayfalara istediğiniz rengi verebiliyorsunuz. Kendinden reklam engelleyici özelliği de bulunuyor. Sielo browser tamamen hızlı, görsel ve pratik kullanım üzerine geliştirilmiş. Görselliği ve pratik kullanmayı sevenler için denemeye değer. Resmi web sitesi ve indirme adresi: Sielo Browser

 Dissenter web browser

Dissenter browser, Brave browserin birebir kopyası. Hızlılığa, güvenliğe ve tarayıcı arayüzünden mesajlaşmaya ağırlık verilmiş
Chrome eklentileri eklenebiliyor, Türkçe ve görevini iyi yapıyor. Dissenter geliştiricinin anlatımını okuyalım.
‘Dissenter nedir?
Dissenter, reklamverenler için değil, İnsanlar için oluşturulmuş açık kaynaklı bir web tarayıcısıdır. Dissenter, tek tek URL’ler etrafında konuşmalar düzenler ve üzerinde herkesin yorum bırakabileceği genel bir kare oluşturur. Dissenter tarayıcısı, varsayılan olarak reklamları ve izleyicileri engeller, böylece web’de gezinme deneyiminizi geleneksel web tarayıcılarından çok daha hızlı hale getirir. Dissenter, geçişi henüz yapmaya hazır değilseniz ve genel yorum sistemimizi diğer tarayıcılarda test etmek istemeniz durumunda, diğer tarayıcılar için de bir uzantı sunar.’  Buradan indirin: Dissenter Browser

Naver Whale  web browser

Bu tarayıcıyı Koreliler inşa etmiş, güzel bir hedefe sahip. Tarayıcının temelini yükledikten sonra içeriğini yani temel yapısını kendine göre özelleştiriyorsun. API sayfası var, kişisel bütün özelleştirmeler oradan yapılıyor. Sayısız gönüllülerin katılımıyla şekilleniyor, yani siz kurduğunuzda ne görüyorsanız sizin gibi kullanıcıların yaptıklarını görmüş oluyorsunuz. Herkesin katıldığı bir blog sayfası var, herkes önerilerini, görüşlerini ve tarayıcıya yaptığı işlemleri orada paylaşıyor, en çok beğenilenler ana sayfanın en üstünde teşhir ediliyor. Bu tarayıcıdan şikayetin olduğunda muhatabın yine kendin oluyorsun, sorununu blog sayfasında paylaştığında binlerce kullanıcının önerisiyle karşılaşıyorsun. Chromium tabanlı, Chrome eklentileri eklenebiliyor, önemli yerleri Türkçe. Buradan indir: Naver Whale browser

OhHai web browser

OhHai tarayıcı sıfırdan inşa edilmiş, istendiği kadar sekmelerle çalışabilmek amacıyla yapılmış. Bütün sekmeleri yan tarafta tutuyor, ileri-geri alma, yer imine ekleme, yenileme ve yeni sekme açma özelliklerinden ibaret. Şimdilik başka özellik taşımıyor, lakin sorunsuz çalışan ve sade bir tarayıcı isteyenler için iyi bir tercih olabilir. Buradan indirin: OhHai browser

Spez web browser

Spez browser gelişmiş bir tarayıcı olmakla birlikte Epiphany tarayıcının zarif görünümlü bir çatalı. Geliştirici şöyle tanımlamış.
‘Güçlü gizlilik ayarları, basit inteface ve gerçekten güvenilir bir şekilde internette gezinmenizi sağlayan adblock özelliklerine sahip, özgürlüğünüz ve gizliliğiniz için güçlü web tarayıcısı. Web’in özel, sade, temiz, güzel bir görünümünü arıyorsanız, bu sizin için bir tarayıcıdır.’ Buradan indirin: Spez browser

Youtube Music

Bir de sizlere farklı bir tarayıcı tanıtayım, bu tarayıcı internette gezmek için değil, Youtube sitesinde gezmek için. Youtube arayüzünü kendine göre müthiş geliştirmiş, videoları kendi penceresinde ve harici pencerede oynatabiliyor. Bir sanatçıya veya videoya ait ne varsa tarihine, resimlerine kadar bütün bilgileri getiriyor ve sunu şeklinde gösteriyor. Yıllara göre, türe göre ve yerli-yabancı sanatçılara göre kategori oluşturuyor, böylece tercih ve kullanım daha pratik oluyor. Kendi kitaplığını oluşturabiliyor, yorumda ve paylaşımda bulunabiliyorsun. Reklam engelleyici, kısıtlı mod, geçmişi temizleme gibi özelliklere sahip.

Ayrıca AppImage formatlı olduğu için kurmadan kullanabilirsiniz, bunun için indirdiğiniz AppImage dosyasına çift tıklamanız yeterli. Buradan indirin: Youtube Music

Pek bilinmeyen altı tane web browser

GNU/Linux için yapılmış ama henüz dağıtım depolarına girmemiş 7 tane farklı web tarayıcıyı ile tanışacağız. Bu tarayıcıların kimisi muhtemelen zaman içinde depolara girecek, kimisi belki hiç giremeden durdurulacak, o kadarını bilemeyiz ama en azından yenilik adına onlara göz atmakta fayda var. Sielo web browser Resimde görülen tarayıcının adı Sielo, bir Fransız tarafından geliştirilmiş,

May 22, 2020

Linux: Ventoy ile Çoklu Önyüklenebilir(Multiboot) USB Sürücü Oluşturma

 

Ventoy, çoklu önyüklenebilir(multiboot) USB sürücüler oluşturmak için ücretsiz, açık kaynaklı ve çapraz platform desteği (Windows/Linux) sunan bir programdır.USB aygıtlarınızı tekrar tekrar biçimlendirmeniz gerekmez.Sadece bir kez önyüklenebilir bir USB sürücü oluşturur ve sonrasında istediğiniz kadar ISO ekleyebilir/çıkartabilirsiniz.Tek yapmanız gereken, Ventoy ile oluşturduğunuz USB belleğe istediğiniz ISO dosyasını kopyalamak.Ventoy, yeni eklenen ISO’lar için menü girişlerini otomatik olarak oluşturur ve önyükleme menüsüne ekler.Size de istediğiniz sistemi seçip kullanmak kalır.

Ventoy, aşağıda bazıları listelenen bir çok kullanışlı özelliğe sahiptir:

Kurulumu ve kullanımı çok kolaydır.

*Hızlıdır (Hızı, iso dosyasını kopyalama hızı ile sınırlıdır).

*ISO dosyalarını Vntoy ile biçimlendirilmiş USB belleğe sadece kopyalamak yeterlidir.ISO dosyasından doğrudan önyükleme yapar.

*Legacy ve UEFI destekler.

*4 GB’tan büyük ISO dosyalarıyla önyüklenebilir sürücüler oluşturabilir.

*Çok sayıda sistemi destekler.Geliştiricisi, Ventoy ile 200’den fazla ISO dosyasının test edildiğini bildirmektedir.

*Önyükleme sırasında USB sürücüsü salt okunurdur.

*USB sürücülerin normal kullanımını etkilemez. Yani USB sürücülerini başka amaçlarla da kullanabilirsiniz (Örn. dosya kopyalama)

*Önyüklenebilir USB sürücüsünü yeniden oluşturmadan yeni bir sürüm çıktığında Ventoy’u yükseltebilirsiniz.Sürüm yükseltme sırasında veriler zarar görmez.

*Yeni bir dağıtım yayınlandığında Ventoy’u güncellemeye gerek yoktur.

*Yeni bir işletim sistemi eklemek için ISO’yu USB sürücüsüne kopyalayıp yapıştırmanız yeterlidir, tekrar başlamanıza gerek yoktur.

*Memdisk modunu destekler. Bazı makinelerde ISO’lar yüklenmeyebilir. Bu gibi durumlarda Memdisk modu kullanılabilir.Bu modda Ventoy, tüm ISO dosyasını belleğe yükler ve ardından önyükleme yapar.

*Çapraz platform desteği vardır.(Linux ve Windows’u destekler.)

*Ücretsiz ve açık kaynaktır!

Nasıl Yapılır?

Önce, önyüklenebilir olarak hazırlayacağımız belleğimizin detaylarını öğrenelim:

[kesim@archikia ~]$ sudo fdisk -l

Çıktıda görüldüğü gibi, benim belleğim /dev/sda olarak görünüyor.

[kesim@archikia ~]$ sudo fdisk -l
Disk /dev/nvme0n1: 238,49 GiB, 256060514304 bayt, 500118192 sektör
Disk model: ADATA SX8200PNP                         
Birimler: sektör'i 1 * 512 = 512 baytın 
Sektör boyutu (montıksal/fiziksel): 512 bayt / 512 bayt
G/Ç boyutu (en düşük/en uygun): 512 bayt / 512 bayt
Disketikeri tipi: dos
Disk belirleyicisi: 0xa952d09f

Aygıt          Açılış Başlangıç       Son    Sektör Boyut ld Türü
/dev/nvme0n1p1 *           2048   1187839   1185792  579M  7 HPFS/NTFS/exFAT
/dev/nvme0n1p2          1187840 102402047 101214208 48,3G  7 HPFS/NTFS/exFAT
/dev/nvme0n1p3        102402048 368642047 266240000  127G  7 HPFS/NTFS/exFAT
/dev/nvme0n1p4        368644094 500117648 131473555 62,7G  5 Ek
/dev/nvme0n1p5        368644096 370642943   1998848  976M 82 Linux takas / Solar
/dev/nvme0n1p6        370644992 500117648 129472657 61,8G 83 Linux

Disk /dev/sda: 14,43 GiB, 15483273216 bayt, 30240768 sektör
Disk model: DataTraveler 2.0
Birimler: sektör'i 1 * 512 = 512 baytın 
Sektör boyutu (montıksal/fiziksel): 512 bayt / 512 bayt
G/Ç boyutu (en düşük/en uygun): 512 bayt / 512 bayt
Disketikeri tipi: dos
Disk belirleyicisi: 0x5e0caad7 Aygıt      Açılış Başlangıç      Son   Sektör Boyut ld Türü
/dev/sda1              2048 30175231 30173184 14,4G  7 HPFS/NTFS/exFAT
/dev/sda2  *       30175232 30240767    65536   32M ef EFI (FAT-12/16/32)
[kesim@archikia ~]$ 

Ardından, Ventoy’un en son sürümünü yazılımın sürüm sayfasından indiriyoruz.Bu yazı yazılırken en son sürüm 1.0.10 idi.İndirdiğimiz dosyayı şıkıştırılmış klasörden çıkarıyoruz ve ventoy-1.0.10 klasörünün içinde bir terminal(uçbirim) açıyoruz.Aşağıdaki komutu çalıştırarak çoklu önyüklenebilir USB belleğimizi oluşturuyoruz.(/dev/sda yerine siz kendi USB sürücünüzün ismini yazmalısınız.)


[kesim@archikia ventoy-1.0.10]$ sudo sh Ventoy2Disk.sh -I /dev/sda

*************************************************la**********
*                Ventoy2Disk Script                       *
*             longpanda  admin@ventoy.net                 *
***********************************************************

Disk : /dev/sda
Model: Kingston DataTraveler 2.0 (scsi)
Size : 14 GB

Attention:
You will install Ventoy to /dev/sda.
All the data on the disk /dev/sda will be lost!!!

Continue? (y/n)y

All the data on the disk /dev/sda will be lost!!!
Double-check. Continue? (y/n)y

Create partitions on /dev/sda ...
Done
mkfs on disk partitions ...
create efi fat fs ... mkfs.fat 4.1 (2017-01-24)
success
mkexfatfs 1.3.0
Creating... done.
Flushing... done.
File system created successfully.la
writing data to disk ...
sync data ...
esp partition processing ...

Install Ventoy to /dev/sda successfully finished.

[kesim@archikia ventoy-1.0.10]$

İşlemi onaylamamız istenecektir, y yazıyoruz ve ENTER‘a basıyoruz:

İşlem tamamlandı, çoklu önyüklenebilir(multiboot) belleğimiz hazır.Artık tek yapmamız gereken ISO dosyalarımızı belleğin içine kopyalamak ve sistemi hazırladığımız bellekten başlatmak!

Yaptığım Denemelerim ve Elde Etttiğim Sonuçları

Ben halihazırda elimde dulunan dört adet dağıtımın ISO’suyla denemeler yaptım.

Elde ettiğim sonuçlar şu şekilde:

cinnamonremix-19.10-all.20191204; ne UEFI, ne Legacy modunda, ne de Memdisk ile açılmadı.

debian-10.2.0-amd64-netinst; UEFI modunda sorunsuz açılırken, Legacy modunda açılmadı.Memdisk ile denemedim.

endeavouros-2020.04.11-x86_64; Legacy modunda sorunsuz açıldı.

ubuntu-20.04-desktop-amd64; Legacy modunda sorunsuz açıldı.

Son Söz: Ventoy, sürüm sayfasındaki sürüm numaralarından anlaşılabileceği üzere, geliştirilmekte olan bir dağıtım.Henüz bazı hatalarla karşılaşılsa da, gelişme süreciyle birlikte büyük kolaylık sağlayacak bir yazılım olarak değerlendirilebilir.

 

 

 

 

Gdebi nasıl çalışır?

Debian ve Ubuntu son sürümlerinde paket kurucu Gdebi yazılımı çalışmıyor. Aylardır beklememe rağmen bu sorunu bir türlü gidermediler. Ben de Gdebi ile paket kurulumu için başka bir çözüm buldum. Gdebi sizde de çalışmıyorsa alttaki iki işleme başlayalım. Birinci işlem 1- Dosya yöneticinizi açın, ctrl-h tuşları ile gizlileri görünür yapın. 2- .config dizininde bulunan mimeapps.list dosyasını

May 21, 2020

Openbox: Harici Monitöre Yansıtılan Görüntüleri Saklama

13.3 inç ekranlı laptopumu, 21 inç monitörüme yansıtarak kullanıyorum.Her iki cihazın çözünürlüğü de 1920×1080; yani FHD.Yasıtmada sorun yok.Gel gör ki, ayarları yaptıktan sonra, ayarların saklanmasında sorun var.Bunun da nedeni, Openbox kullanıyor olmam.

Ayarları Lxrandr ile yapıyorum.Resimde görüldüğü üzere, eDP-1, dizüstü bilgisayarım.HDMI-1 ise, monitörüm.eDP-1‘in tikini kaldırdığımda, dizüstü bilgisayarımın monitörünü pasif duruma getirmiş oluyorum ve sadece monitörümden görüntü alıyorum.Yani bu durumda dizüstü bilgisayarımı kasa gibi kullanmış oluyorum.Eğer her ikisini de aktif edersem(HDMI-1-eDP-1) hem dizüstü bigisayarımdan, hem de monitörümden görüntü alabiliyorum.

Aynı işlemleri, yine aşağıdaki resimlerde görüldüğü üzere arandr ile de yapabiliyorıum.

 

Buraya kadar her şey yolunda.Ne var ki, Bilgisayarı yeniden başlattığımda, ayarlar saklanmıyor, kayboluyor.Elbette bu durum Openbox harici masaüstü ortamlarında söz konusu değil.Onların görüntü ayar programları ile yapılan ayarlamalar sorunsuz bir şekilde saklanıyor ve bir sonraki oturumda etkin olarak geliyor.

Bu sorunun çözümü ise autorandr!

İlk önce autorandr paketini sistemimize kurmamız gerekiyor.

sudo apt install autorandr

Sonrasında ise ayarladığımız profili autorandr yardımıyla kaydetmemiz gerekiyor.Bir uçbirim(terminal) açarak aşağıdaki komutu yürütüyoruz:

autorandr --save mobile

İşlem tamam, artık bilgisayarı yeniden başlattığımızda yaptığımız ayarlar etkin olarak gelecek ve dizüstü bilgisayarımızın görüntüsü sorunsuz olarak monitörümüze aktarılmış olacak.

 

May 18, 2020

İlledelinux Debian Xfce 1-2-20 sürümü kullanıma hazır

İlledelinux Debian Xfce 1-2-20 sürümü bir önceki sürümün devamı ve kullanıma hazırdır. Bu sürümde sayıca az ama emekte çok sayılabilecek işlemler yapıldı. Bazı düzenlemeler ve eklemeler ile sistem daha kullanışlı duruma getirildi. ----------------------------------------------------------- Bunları anlatmadan önce elzem gördüğüm bir konuya değinmek istiyorum. İlledelinux, markası, logosu, kendi

May 17, 2020

我們不一樣

Bu ara site istatistiklerimde ismen bildiğim ama hiç araştırmadığım bir arama motoru karşıma çıkıp duruyordu, Baidu. Pandemi ile birlikte Çin’e duyduğum merak da bir miktar daha artmıştı. Üzerine bu rastlantı ile araştırmaya başladım. Çok kabaca söylemek gerekirse Baidu çılgın bir arama motoru. Sitenizi ekleyin! şekilli anlatımlar nedeniyle araştırmaya başladım. Ve bu güne kadar sadece söylenti şeklinde duymuş olduğum Çin’deki internet denetiminin nasıl bir şey olduğunu tecrübe etmiş oldum.

Başta çeviri programlarıyla çözülemeyecek sorun olmadığını düşünüyordum. Büyük yanılgıymış. Bi kere QQ‘dan bi mail adresi alabilmem yaklaşık 1 saat sürdü. Her yerden bi barkotlar çıkıyor. Telefon doğrulama kodu mesajlarıyla doldu. Neden bi QQ mailine ihtiyacım vardı peki? Çünkü Baidu belirli mail servisleri dışında mail adresi kabul etmiyor. Nerde mi? Hah ilk deneme aslında bir Baidu hesabı açabilmekti. O ara anladım bu gerçeği. Normalde farklı dillerdeki sitelerde ‘kas hafızası’ yardımıyla doğru yolu buluyorum. Fakat Çince beni sadece tamamen anlaşılmaz olan karakterleriyle zorlamadı. Sitelerdeki dizilişler de alışılmıştan farklıydı. Giriş olması gereken yer Şifremi Unuttum ‘a denk getirilmiş. Kayıt olmaya çalışıyorum. İleri, yok o İptalmiş.

Arada bi de WeChat olayına bakınayım dedim. Tavsiyesiz giremiyosunuz. Baya garip işler, sizi bu programın en az 6 aylık kullanıcısı olan ban yememiş birinin onaylaması gerekiyor. Hatta detaylandırayım bunu 40$ karşılığında hesabımı onaylamayı teklif etti biri, bunun bi piyasası olduğunu gördüğüme baya şaşırdım açıkçası.

Sonunda her şeyi başardım bir mail, bir hesap. Log tutuyorlar evet, tüm kayıtlarım ortada. IP‘den sistemime kadar. VPNlemedim. Bi sürü de yeni uygulama oldu telefonumda, değişik, geniş ve birbiriyle oldukça sıkı bağlantılı bir dünya. Gördük birazını bugün Ubuntu.

没有水的河

May 16, 2020

Putty ile parolasız ssh bağlantısı nasıl yapılır

Putty ile parolasız ssh bağlantısı nasıl yapılır

Bu yazıda bazı vps sağlayıcıları parola ile erişim yerine daha güvenli olan ssh key ile erişim sağlamayı tercih edebiliyorlar.

Bir arkadaşım kendisine key verildiğini ve bu keyi putty ile nasıl kullanacağını sordu.

 

burada yapacağımız işlem keyin putty ile kullanabilir hale getirmek.

PuttyPenceresi açılıp load butonu ile key dosyası import edilir.

bize verilen id_rsa dosyası seçilir.

Evet yanıtı ile import edilen key dosyası ppk uzantısı verilerek kaydedilir.

Putty ile kullanacağımız ppk dosyası oluştu

Kullanıcı adı ve ip adresi girilır ve key dosyasını kullanmak için SSH  altındaki AUTH tıklanır.

Browse tuşu ile oluşturduğumuz ppk dosyası seçilir.

 

ppk dosyasını seçip onayladıkttan sonra Open tuşu tıklanır.

Gördüğünüz gibi parola sorulmadan bağlantı kuruldu.

Faydalı olması dileğiyle.

 

İlledelinux Dünya TV'leri

Türkiye de dahil 5 Kıta ve 90 tane ülke TV'lerini izleme şansı bulabileceğimiz bir paket oluşturdum. Dünyadaki TV'leri izlemek için kısayol simgesine tıkladığınızda sistem panelinin dockbarına yerleşiyor. Resimde sağ tarafta görüldüğü gibi ülke tuşlarını barındıran pencereden istediğiniz ülke veya Kıta'nın tuşuna tıkladığınızda video oynatıcı ile TV'leri izliyorsunuz. Sisteminizde Celluloid,

Ve Kapanış...


Vakit bulamadığımdan veya başka nedenler bilemiyorum buraya gereken ilgiyi gösteremedim. Bu blogtaki bir çok yazı da güncelliğini yitirdi. Bundan dolayıdır ki artık burada manasızca yer tutmanın anlamlı olmadığını düşündüğümden artık bu platformdaki varlığımı bir müddet sonra sonlandırıyor olacağım.

Yakın zamanda belki başka platformlarda yeniden blog tutmaya başlarsam https://twitter.com/birtanyildiz dan yazarım belki. Belki diyorum çünkü oraya da pek vakit ayıramadım. 
Yeniden yazma heyecanını kazanma ümidi ile... Esen kalın.

İrdelemeler: Tamamen Kişisel, Ubukia 18.04

Linux dunyasinda seçenekler o kadar çoktur ki, neredeyse imkansiz diye bir sey yoktur.Sınır, kullanıcının hayallerinin eriştiği yerdir.

O dağıtımı beğenmediysen, bu dağıtımı denersin…Falanca masaüstü ortamı sana göre değilse, filancası ne güne duruyor?Her şeyin bir alnernatifi muhakkak var.Hiçbiri uymadı mı sana, yatmadı mı kafana bir tanesi?Hadi o zaman, kendi dağıtımını kendin yap, ne duruyorsun!Kim tutuyor seni?

Evet evet, işte bu kadar da esnektir Linux alemi.Yeter ki sen iste, her şeyi verir.İşte bu nedenlerle ben de hazır dağıtım kullan(a)mıyorum.Kendime göre sıfırdan, Ubuntu 18.04 üzerine temelden yapılandırdığım ve Ubukia adını verdiğim bir dağıtım kullanıyorum.(Evet, her ne kadar dağıtmıyorsam da, halihazırdaki dağıtımlardan her yönüyle oldukça farklı ve kişiselleştirilmiş olduğu için dağıtım olarak adlandırmakta bir sakınca görmüyorum.) 

Ubukia 18.04 sistemim tamamen Openbox üzerine kurulu.Hiçbir masaüstü ortamını temel olarak almıyor kendisine.Tamamen bağımsız bir Openbox masaüstü ortamı olarak tanımlayabilirim.

Kendi dagıtımını, kendi masaüstü ortamını yapma konusunda en iyi iki dağıtım Debian ve Arch Linux’tur.(Her ne kadar ben Ubuntu 18.04 kullandıysam da…)Her ikisiyle de yapabileceklerinizin sınırını siz belirlersiniz.

Yazının buraya kadar olan kısmından gayet kolaylıkla anlaşılabileceği üzere, bu yazının ana malzemesi, Ubuntu 18.04 üzerine yapılandırdığım Openbox masaüstü ortamıdır.(Ki normalde böyle bir masaüstü ortamı yoktur, çünkü Openbox temelde bir pencere yöneticisidir.Ancak o kadar esnek ve yapılandırılabilirdir ki, doğru araç ve uygulamalarla tam takım ve bağımsız bir masaüstü ortamına rahatlıkla dönüştürülebilir.)

Tamamen kendi zevkime göre yapılandırdığım bu sistem, kullanıcının Linux ile yapabileceklerinin sadece küçük ve basit bir örneğidir.Elbette yapılacaklar kullancının bilgi, tecrübe, yetenek, istek ve hayallerine bağlı olarak çok daha farklı yerlere götürülebilir.

Ubukia 18.04’ü oluştururken kullandığım temel programlar:

Openbox(Pencere yöneticisi)

Tint2(panel ve uygulama başlatıcı)

Jgmenu(Menü)

Pcmanfm(Dosya yöneticisi)

Leafpad(Metin editörü)

Nitrogen(Masaüstü resmi değiştirici)

Obmenu(Menü düzenleme)

Obconf(Openbox yapılandırma aracı)

Lxappearance(Görünüm özlleştirme)

Lxterminal(Uçbirim)

Xfce4-screenshooter(Ekran görüntüsü)

Bu temel program ve uygulamaların yanında irili ufaklı diğerleri ve Bunsenlabs araçları…

O halde, Ubukia 18.04’e aşağıdaki resim galerisinden yararlanarak daha yakından bakalım!

[See image gallery at www.webguncesi.com]

May 13, 2020

Linux: Ubuntu 20.04’te Firefox Üzerinde Facebook Videolarının Oynatılamama Sorunu ve Çözümü

Ubuntu 20.04 kullanımımda, Firefox ile Facebook videolarını izlemeye çalıştığmda, açılmama sorunu ile karşı karşıya kaldım.Videolar görünmesine rağmen, oynatılamıyor, oynatma düğmesine tıkladığımda hiç bir şey olmuyordu.Halbuki, Youtube videolarını sıkıntısız oynatıyordu tarayıcı.

Bunun sebebi eksik olan kısıtlı medya kodekleridir.Ubuntu’da lisans sorunlarından dolayı kısıtlı(restricted) medya kodekleri önyüklü olarak gelmiyor.Ancak, depolarda hazır bulunuyor.Böylece, yükleme ya da yüklememe sorumluluğunu kullanıcıya bırakmış oluyor Ubuntu.Ben yükledim…

Uçbirimden(terminal) asiağıdaki komutu yürütmek bunun için yeterli:

sudo apt install ubuntu-restricted-extras

Aynı şekilde Kubuntu, Lubuntu ve Xubuntu için de yüklemek mümkün:

sudo apt install kubuntu-restricted-extras
sudo apt install lubuntu-restricted-extras
sudo apt install xubuntu-restricted-extras

Kısıtlı medya kodekleri Synaptic üzerinden de yüklenebilir.Bunun için ubuntu-restricted-extras paketini aratıp, işaretleyerek yüklemesini sağlamak yeterlidir.

Yükleme işleminden sonra tarayıcıyı yeniden başlatmak gerekebilir.

May 12, 2020

Debian'a LMDE nasıl eklenir?

LMDE "Linux Mint Debian Edition" çoğumuzun bildiği gibi Debian Stable tabanlı bir dağıtımdır. Mint topluluğu bu dağıtım için bir çok yararlı yazılım geliştirmiş. Resimlerde göründüğü gibi bu yazılımlar bir çok işi kolaylaştıran, oldukça kullanışlı ve son kullanıcıyı hedef alarak geliştirilmiş. Debian'ı daha kullanışlı yapmak isteyenler için gerçekten güzel bir imkan. Üstelik kararlı olduğu için

May 10, 2020

Exiting/Terminating Python scripts (Simple Examples)

Today, we’ll be diving into the topic of exiting/terminating Python scripts! Before we get started, you should have a basic understanding of what Python is and some basic knowledge about its use. You can use the IDE of your choice, but I’ll use  Microsoft’s Linux Subsystem for Windows (WSL) package this time. For more information on that and how you enable it on Windows 10 go here. The way Python executes a code block makes it execute each line in order, checking dependencies to import, reading definitions and classes to store in memory, and executing pieces of code in order allowing for loops and calls back to the defined definitions and classes. When the Python interpreter reaches the end of the file (EOF), it notices that it can’t read any more data from the source, whether that be the user’s input through an IDE or reading from a file. To demonstrate let’s try to get user input and interrupt the interpreter in the middle of execution!

Why does Python automatically exit a script when it’s done?

First, from your bash terminal in your PowerShell open a new file called “input.py”

nano input.py

Then paste the following into the shell by right-clicking on the PowerShell window

name=input("Don't type anything!\n")

print("Hi,",name,"!")

Now, press CTRL+X to save and exit the nano window and in your shell type:

python3 input.py
Don't type anything!

And press CTRL+D to terminate the program while it’s waiting for user input

Traceback (most recent call last):

File "input.py", line 1, in

name=input("Don't type anything!")

EOFError

The EOFError exception tells us that the Python interpreter hit the end of file (EOF) condition before it finished executing the code, as the user entered no input data.

When Python reaches the EOF condition at the same time that it has executed all the code it exits without throwing any exceptions which is one way Python may exit “gracefully.”

Detect script exit

If we want to tell when a Python program exits without throwing an exception, we can use the built-in Python atexit module.

Theatexit handles anything we want the program to do when it exits and is typically used to do program clean up before the program process terminates

To experiment with atexit, let’s modify our input.py example to print a message at the program exit. Open the input.py file again and replace the text with this

import atexit

atexit.register(print,"Program exited successfully!")

name=input("What's your name?\n")

print("Hi,",name,"!")

Type your name and when you hit enter you should get:

What's your name?
Example
Hi, Example !
Program exited successfully!

Notice how the exit text appears at the end of the output no matter where we place the atexit call, and how if we replace the atexit call with a simple print(), we get the exit text where the print() all was made, rather than where the code exits.

Program exited successfully!
What's your name?
Example
Hi, Example !

Graceful exit

There are several ways to exit a Python Program that doesn’t involve throwing an exception, the first was going to try is quit()

You can use the bash command echo $? to get the exit code of the Python interpreter.

python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
$ echo $?
0

We can also define the type of code the interpreter should exit with by handing quit() an integer argument less than 256

python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit(101)
$ echo $?
101

exit() has the same functionality as it is an alias for quit()

python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit(101)
$ echo $?
101

Neither quit() nor exit() are considered good practice, as they both require the site module which is meant to be used for interactive interpreters and not in programs. For our programs, we should use something like sys.exit

python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.exit(101)
$ echo $?
101

Notice that we need to explicitly import a module to call exit(), this might seem like its not an improvement but it guarantees that the necessary module is loaded because it’s not a good assumption site will be loaded at runtime. If we don’t want to import extra modules, we can do what exit()quit() and sys.exit() are doing behind the scenes and raise SystemExit

python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> raise SystemExit(101)
$ echo $?
101

Exit with error messages

What if we get bad input from a user? Let’s look back at our input.py script, and add the ability to handle bad input from the user (CTRL+D to pass an EOF character)

nano input.py
try:

name=input("What's your name?\n")

print("Hi, "+name+"!")

except EOFError:

print("EOFError: You didn't enter anything!")

$ python3 input.py
What's your name?
EOFError: You didn't enter anything!

The try statement tells Python to try the code inside the statement and to pass any exception to the except statement before exiting.

Exiting without error

What if the user hands your program an error but you don’t want your code to print an error, or to do some sort of error handling to minimize user impact?

We can add a finally statement that lets us execute code after we do our error handling in catch

nano input.py
try:

name=input("What's your name?\n")

if(name==''):

print("Name cannot be blank!")

except EOFError:

#print("EOFError: You didn't enter anything!")
name="Blankname"

finally:

print("Hi, "+name+"!")

$ python3 input.py
What's your name?
Hi, Blankname!

Notice the user would never know an EOFError occurred, this can be used to pass default values in the event of poor input or arguments.

Exit and release your resources

Generally, Python releases all the resources you’ve called in your program automatically when it exits, but for certain processes, it’s good practice to encase some limited resources in a with block.

Often you’ll see this in open() calls, where failing to properly release the file could cause problems with reading or writing to the file later.

nano openfile.py
with open("testfile.txt","w") as file:

file.write("let's write some text!\n")

$ python3 openfile.py
$ cat testfile.txt
let's write some text!

The with block automatically releases all resources requisitioned within it. If we wanted to more explicitly ensure the file was closed, we can use the atexit.register() command to call close()

$ nano openfile.py
import atexit

file=open("testfile.txt","w")

file.write("let's write some text!\n")

atexit.register(file.close)

If resources are called without using a with block, make sure to explicitly release them in an atexit command.

Exit after a time

If we are worried our program might never terminate normally, then we can use Python’s multiprocessing module to ensure our program will terminate.

$ nano waiting.py
import time

import sys

from multiprocessing import Process

integer=sys.argv[1]

init=map(int, integer.strip('[]'))

num=list(init)[0]

def exclaim(int):

time.sleep(int)

print("You were very patient!")

if __name__ == '__main__':

program = Process(target=exclaim, args=(num,))

program.start()

program.join(timeout=5)

program.terminate()

$ python3 waiting.py 7
$ python3 waiting.py 0
You were very patient!

Notice how the process failed to complete when the function was told to wait for 7 seconds but completed and printed what it was supposed to when it was told to wait 0 seconds!

Exiting using a return statement

If we have a section of code we want to use to terminate the whole program, instead of letting the break statement continue code outside the loop, we can use the return sys.exit() to exit the code completely.

$ nano break.py
import time

import sys

def stop(isTrue):

for a in range(0,1):

if isTrue:

break

else:

print("You didn't want to break!")

return sys.exit()

mybool = False

stop(mybool)

print("You used break!")

Exit in the middle of a function

If we don’t want to use a return statement, we can still call the sys.exit() to close our program and provide a return in another branch. Let’s use our code from break.py again.

$ nano break.py
import time

import sys

def stop(isTrue):

for a in range(0,1):

if isTrue:

word="bird"

break

else:

print("You didn't want to break!")

sys.exit()

mybool = False

print(stop(mybool))

Exit when conditions are met

If we have a loop in our Python code and we want to make sure the code can exit if it encounters a problem, we can use a flag that it can check to terminate the program.

$ nano break.py
import time

import sys

myflag=False

def stop(val):

global myflag

while 1==1:

val=val+1

print(val)

if val%5==0:

myflag=True

if val%7==0:

myflag=True

if myflag:

sys.exit()

stop(1)

$ python3 break.py
2
3
4
5

Exit on keypress

If we want to hold our program open in the console till we press a key, we can use an unbound input() to close it.

$ nano holdopen.py
input("Press enter to continue")
$ python3 holdopen.py
Press enter to continue
$

We can also pass CTRL+C to the console to give Python a KeyboardInterrupt character. We can even handle the KeyboardInterrupt exception like we’ve handled exceptions before.

$ nano wait.py
import time

try:

i=0

while 1==1:

i=i+1

print(i)

time.sleep(1)

except KeyboardInterrupt:

print("\nWhoops I took too long")

raise SystemExit

$ python3 wait.py
1
2
3
^C

Whoops I took too long

Exit a multithreaded program

Exiting a multithreaded program is slightly more involved, as a simple sys.exit() is called from the thread that will only exit the current thread. The “dirty” way to do it is to use os._exit()

$ nano threads.py
import threading

import os

import sys

import time

integer=sys.argv[1]

init=map(int, integer.strip('[]'))

num=list(init)[0]

def exclaim(int):

time.sleep(int)

os._exit(1)

print("You were very patient!")

if __name__ == '__main__':

program = threading.Thread(target=exclaim, args=(num,))

program.start()

program.join()

print("This should print before the main thread terminates!")

$ python3 threads.py 6
$

As you can see, the program didn’t print the rest of the program before it exited, this is why os._exit() is typically reserved for a last resort, and calling either Thread.join() from the main thread is the preferred method for ending a multithreaded program.

$ nano threads.py

import threading

import os

import sys

import time

import atexit

integer=sys.argv[1]

init=map(int, integer.strip('[]'))

num=list(init)[0]

atexit.register(print,"Threads exited successfully!")

def exclaim(int):

time.sleep(int)

print("You were very patient!")

if __name__ == '__main__':

program = threading.Thread(target=exclaim, args=(num,))

program.start()

program.join()

$ python3 threads.py 6
You were very patient!
Threads exited successfully!

End without sys exit

Sys.exit() is only one of several ways we can exit our python programs, what sys.exit() does is raise SystemExit, so we can just as easily use any built-in Python exception or create one of our own!

$ nano myexception.py
class MyException(Exception):

pass

try:

raise MyException()

except MyException:

print("The exception works!")

$ python3 myexception.py
The exception works!

We can also use the os._exit() to tell the host system to kill the python process, although this doesn’t do atexit cleanup.

$ python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os._exit(1)

Exit upon exception

If we want to exit on any exception without any handling, we can use our try-except block to execute os._exit().

Note: this will also catch any sys.exit()quit()exit(), or raise SystemExit calls, as they all generate a SystemExit exception.

$ python3
Python 3.8.2 (default, Apr 1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> try:
... quit()
... except:
... os._exit(1)
...
$ echo $?
1

Exit and restart

Finally, we’ll explore what we do to exit Python and restart the program, which is useful in many cases.

$ nano restart.py
import atexit

import os

atexit.register(os.system,"python3 restart.py")

try:

n=0

while 1==1:

n=n+1

if n%5==0:

raise SystemExit
except:

print("Exception raised!")

$ python3 restart.py
Exception raised!
Exception raised!
...
Exception raised!
^Z
[3]+ Stopped python3 restart.py

I hope you find the tutorial useful. Keep coming back.

Thank you.

20+ examples for NumPy matrix multiplication

In this tutorial, we will look at various ways of performing matrix multiplication using NumPy arrays. we will learn how to multiply matrices with different sizes together. Also. we will learn how to speed up the multiplication process using GPU and other hot topics, so let’s get started! Before we move ahead, it is better to review some basic terminologies of Matrix Algebra. Basic Terminologies: Vector: Algebraically, a vector is a collection of coordinates of a point in space. Thus, a vector with 2 values represents a point in a 2-dimensional space. In Computer Science, a vector is an arrangement of numbers along a single dimension. It is also commonly known as an array or a list or a tuple. Eg. [1,2,3,4] Matrix: A matrix (plural matrices) is a 2-dimensional arrangement of numbers or a collection of vectors.

Ex:

[[1,2,3],
[4,5,6],
[7,8,9]]

Dot Product: A dot product is a mathematical operation between 2 equal-length vectors.
It is equal to the sum of the products of the corresponding elements of the vectors.
vector dot product operation

With a clear understanding of these terminologies, we are good to go.

Matrix multiplication with a vector

Let’s begin with a simple form of matrix multiplication – between a matrix and a vector.

Before we proceed, let’s first understand how a matrix is represented using NumPy.

NumPy’s array() method is used to represent vectors, matrices, and higher-dimensional tensors. Let’s define a 5-dimensional vector and a 3×3 matrix using NumPy.

import numpy as np

a = np.array([1, 3, 5, 7, 9])

b = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

print("Vector a:\n", a)

print()

print("Matrix b:\n", b)

Output:

Let us now see how multiplication between a matrix and a vector takes place.

The following points should be kept in mind for a matrix-vector multiplication:

  1. The result of a matrix-vector multiplication is a vector.
  2. Each element of this vector is got by performing a dot product between each row of the matrix and the vector being multiplied.
  3. The number of columns in the matrix should be equal to the number of elements in the vector.

matrix vector multiplication
We’ll use NumPy’s matmul() method for most of our matrix multiplication operations.
Let’s define a 3×3 matrix and multiply it with a vector of length 3.

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
b= np.array([10, 20, 30])

print("A =", a)

print("b =", b)

print("Ab =",np.matmul(a,b))

Output:

Notice how the result is a vector of length equal to the rows of the multiplier matrix.

Multiplication with another matrix

Now,  we understood the multiplication of a matrix with a vector, it would be easy to figure out the multiplication of two matrices.
But, before that, let’s review the most important rules of matrix multiplication:

  1. The number of columns in the first matrix should be equal to the number of rows in the second matrix.
  2. If we are multiplying a matrix of dimensions m x n with another matrix of dimensions n x p, then the resultant product will be a matrix of dimensions m x p.

Let us consider multiplication of an m x n matrix A with an n x p matrix B: input matrices A and BC, product of A and B
The product of the two matrices C = AB will have m row and p columns.
Each element in the product matrix C results from a dot product between a row vector in A and a column vector in B.

formula for each element in matrix multiplication result
Let us now do a matrix multiplication of 2 matrices in Python, using NumPy.
We’ll randomly generate 2 matrices of dimensions 3 x 2 and 2 x 4.
We will use np.random.randint() method to generate the numbers.

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 15, size=(3,2))

B = np.random.randint(0, 15, size =(2,4))

print("Matrix A:\n", A)

print("shape of A =", A.shape)

print()

print("Matrix B:\n", B)

print("shape of B =", B.shape)

Output:

Note: we are setting a random seed using ‘np.random.seed()’ to make the random number generator deterministic.
This will generate the same random numbers each time you run this code snippet. This step is essential if you want to reproduce your result at a later point.

You can set any other integer as seed, but I suggest to set it to 42 for this tutorial so that your output will match the ones shown in the output screenshots.

Let us now multiply the two matrices using the np.matmul() method. The resulting matrix should have the shape 3 x 4.

C = np.matmul(A, B)

print("product of A and B:\n", C)

print("shape of product =", C.shape)

Output:

Multiplication between 3 matrices

Multiplication of the 3 matrices will be composed of two 2-matrix multiplication operations and each of the two operations will follow the same rules as discussed in the previous section.

Let us say we are multiplying 3 matrices A, B, and C; and the product is D = ABC.
Here, the number of columns in A should be equal to the number of rows in B and the number of rows in C should be equal to the number of columns in B.

The resulting matrix will have rows equal to the number of rows in A, and columns equal to the number of columns in C.

An important property of matrix multiplication operation is that it is Associative.
With multi-matrix multiplication, the order of individual multiplication operations does not matter and hence does not yield different results.

For instance, in our example of multiplication of 3 matrices D = ABC, it doesn’t matter if we perform AB first or BC first.

diffrent orderings for multiplication of 3 matrices
Both orderings would yield the same result. Let us do an example in Python.

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(2,2))

B = np.random.randint(0, 10, size=(2,3))

C = np.random.randint(0, 10, size=(3,3))

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("Matrix B:\n{}, shape={}\n".format(B, B.shape))

print("Matrix C:\n{}, shape={}\n".format(C, C.shape))

Output:

Based on the rules we discussed above, the multiplication of these 3 matrices should yield a resulting matrix of shape (2, 3).
Note that the method np.matmul() accepts only 2 matrices as input for multiplication, so we will call the method twice in the order that we wish to multiply, and pass the result of the first call as a parameter to the second.
(We’ll find a better way to deal with this problem in a later section when we introduce ‘@’ operator)

Let’s do the multiplication in both orders and validate the property of associativity.

D = np.matmul(np.matmul(A,B), C)

print("Result of multiplication in the order (AB)C:\n\n{},shape={}\n".format(D, D.shape))

D = np.matmul(A, np.matmul(B,C))

print("Result of multiplication in the order A(BC):\n\n{},shape={}".format(D, D.shape))

Output:

As we can see, the result of multiplication of the 3 matrices remains the same whether we multiply A and B first, or B and C first.
Thus, the property of associativity stands validated.
Also, the shape of the resulting array is (2, 3) which is on the expected lines.

NumPy 3D matrix multiplication

A 3D matrix is nothing but a collection (or a stack) of many 2D matrices, just like how a 2D matrix is a collection/stack of many 1D vectors.

So, matrix multiplication of 3D matrices involves multiple multiplications of 2D matrices, which eventually boils down to a dot product between their row/column vectors.

Let us consider an example matrix A of shape (3,3,2) multiplied with another 3D matrix B of shape (3,2,4).

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(3,3,2))

B = np.random.randint(0, 10, size=(3,2,4))

print("A:\n{}, shape={}\nB:\n{}, shape={}".format(A, A.shape,B, B.shape))

Output:

The first matrix is a stack of three 2D matrices each of shape (3,2) and the second matrix is a stack of 3 2D matrices, each of shape (2,4).

The matrix multiplication between these two will involve 3 multiplications between corresponding 2D matrices of A and B having shapes (3,2) and (2,4) respectively.

Specifically, the first multiplication will be between A[0] and B[0], the second multiplication will be between A[1] and B[1] and finally, the third multiplication will be between A[2] and B[2].

The result of each individual multiplication of 2D matrices will be of shape (3,4). Hence, the final product of the two 3D matrices will be a matrix of shape (3,3,4).

Let’s realize this using code.

C = np.matmul(A,B)

print("Product C:\n{}, shape={}".format(C, C.shape))

Output:

Alternatives to np.matmul()

Apart from ‘np.matmul()’, there are two other ways of doing matrix multiplication – the np.dot() method and the ‘@’ operator, each offering some differences/flexibility in matrix multiplication operations.

The ‘np.dot()’ method

This method is primarily used to find the dot product of vectors, but if we pass two 2-D matrices, then it will behave similarly to the ‘np.matmul()’ method and will return the result of the matrix multiplication of the two matrices.

Let us look at an example:

import numpy as np

# a 3x2 matrix
A = np.array([[8, 2, 2],
[1, 0, 3]])

# a 2x3 matrix
B = np.array([[1, 3],
[5, 0],
[9, 6]])

# dot product should return a 2x2 product
C = np.dot(A, B)

print("product of A and B:\n{} shape={}".format(C, C.shape))

Output:

Here, we defined a 3×2 matrix and a 2×3 matrix and their dot product yields a 2×2 result which is the matrix multiplication of the two matrices,
the same as what ‘np.matmul()’ would have returned.

The difference between np.dot() and np.matmul() is in their operation on 3D matrices.
While ‘np.matmul()’ operates on two 3D matrices by computing matrix multiplication of the corresponding pairs of 2D matrices (as discussed in the last section), np.dot() on the other hand computes dot products of various pairs of row vectors and column vectors from the first and second matrix respectively.

np.dot() on two 3D matrices A and B returns a sum-product over the last axis of A and the second-to-last axis of B.
This is non-intuitive, and not easily comprehensible.

So, if A is of shape (a, b, c) and B is of shape (d, c, e), then the result of np.dot(A, B) will be of shape (a,d,b,e) whose individual element at a position (i,j,k,m) is given by:

dot(A, B)[i,j,k,m] = sum(A[i,j,:] * B[k,:,m])

Let’s check an example:

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(2,3,2))

B = np.random.randint(0, 10, size=(3,2,4))

print("A:\n{}, shape={}\nB:\n{}, shape={}".format(A, A.shape,B, B.shape))

Output:

If we now pass these matrices to the ‘np.dot()’ method, it will return a matrix of shape (2,3,3,4) whose individual elements are computed using the formula given above.

C = np.dot(A,B)

print("np.dot(A,B) =\n{}, shape={}".format(C, C.shape))

Output:

Another important difference between ‘np.matmul()’ and ‘np.dot()’ is that ‘np.matmul()’ doesn’t allow multiplication with a scalar (will be discussed in the next section), while ‘np.dot()’ allows it.

The ‘@’ operator

The @ operator introduced in Python 3.5, it performs the same operation as ‘np.matmul()’.

Let’s run through an earlier example of ‘np.matmul()’ using @ operator, and will see the same result as returned earlier:

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 15, size=(3,2))

B = np.random.randint(0, 15, size =(2,4))

print("Matrix A:\n{}, shape={}".format(A, A.shape))

print("Matrix B:\n{}, shape={}".format(B, B.shape))

C = A @ B

print("product of A and B:\n{}, shape={}".format(C, C.shape))

Output:

The ‘@’ operator becomes handy when we are performing matrix multiplication of over 2 matrices.

Earlier, we had to call ‘np.matmul()’ multiple times and pass their results as a parameter to the next call.
Now, we can perform the same operation in a simpler (and a more intuitive) way:

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(2,2))

B = np.random.randint(0, 10, size=(2,3))

C = np.random.randint(0, 10, size=(3,3))

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("Matrix B:\n{}, shape={}\n".format(B, B.shape))

print("Matrix C:\n{}, shape={}\n".format(C, C.shape))

D = A @ B @ C # earlier np.matmul(np.matmul(A,B),C)

print("Product ABC:\n\n{}, shape={}\n".format(D, D.shape))

Output:

Multiplication with a scalar (Single value)

So far we’ve performed multiplication of a matrix with a vector or another matrix. But what happens when we perform matrix multiplication with a scalar or a single numeric value?

The result of such an operation is got by multiplying each element in the matrix with the scalar value. Thus the output matrix has the same dimension as the input matrix.

Note that ‘np.matmul()’ does not allow the multiplication of a matrix with a scalar. This can be achieved by using the np.dot() method or using the ‘*’ operator.

Let’s see this in a code example.

import numpy as np

A = np.array([[1,2,3],
[4,5, 6],
[7, 8, 9]])

B = A * 10

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("Multiplication of A with 10:\n{}, shape={}".format(B, B.shape))

Output:

Element-wise matrix multiplication

Sometimes we want to do multiplication of corresponding elements of two matrices having the same shape.

element-wise matrix multiplication
This operation is also called as the Hadamard Product. It accepts two matrices of the same dimensions and produces a third matrix of the same dimension.

It can be achieved in Python by calling the NumPy’s multiply() function or using the ‘*’ operator.

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(3,3))

B = np.random.randint(0, 10, size=(3,3))

print("Matrix A:\n{}\n".format(A))

print("Matrix B:\n{}\n".format(B))

C = np.multiply(A,B) # or A * B

print("Element-wise multiplication of A and B:\n{}".format(C))

Output:

The only rule to be kept in mind for element-wise multiplication is that the two matrices should have the same shape.
However, if one dimension of a matrix is missing, NumPy would broadcast it to match the shape of the other matrix.

In fact, matrix multiplication with a scalar also involves the broadcasting of the scalar value to a matrix of the shape equal to the matrix operand in the multiplication.

That means when we are multiplying a matrix of shape (3,3) with a scalar value 10, NumPy would create another matrix of shape (3,3) with constant values 10 at all positions in the matrix and perform element-wise multiplication between the two matrices.

Let’s understand this through an example:

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(3,4))

B = np.array([[1,2,3,4]])

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("Matrix B:\n{}, shape={}\n".format(B, B.shape))

C = A * B

print("Element-wise multiplication of A and B:\n{}".format(C))

Output:

Notice how the second matrix which had shape (1,4) was transformed into a (3,4) matrix through broadcasting and the element-wise multiplication between the two matrices took place.

Matrix raised to a power (Matrix exponentiation)

Just like how we can raise a scalar value to an exponent, we can do the same operation with matrices.
Just as raising a scalar value (base) to an exponent n is equal to repeatedly multiplying the n bases, the same pattern is observed in raising a matrix to power, which involves repeated matrix multiplications.

For instance, if we raise a matrix A to a power n, it is equal to the matrix multiplications of n matrices, all of which will be the matrix A.

matrix A raised to power n
Note that for this operation to be possible, the base matrix has to be square.
This is to ensure the rules of matrix multiplication are followed (number of columns in preceding matrix = number of rows in the next matrix)

This operation is provided in Python by NumPy’s linalg.matrix_power() method, which accepts the base matrix and an integer power as its parameters.

Let us look at an example in Python:

import numpy as np

np.random.seed(10)

A = np.random.randint(0, 10, size=(3,3))

A_to_power_3 = np.linalg.matrix_power(A, 3)

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("A to the power 3:\n{}, shape={}".format(A_to_power_3,A_to_power_3.shape))

Output:

We can validate this result by doing normal matrix multiplication with 3 operands (all of them A), using the ‘@’ operator:

B = A @ A @ A

print("B = A @ A @ A :\n{}, shape={}".format(B, B.shape))

Output:

As you can see, the results from both operations are matching.

An important question that arises from this operation is – What happens when the power is 0?
To answer this question, let us review what happens when we raise a scalar base to power 0.
We get the value 1, right? Now, what is the equivalent of 1 in Matrix Algebra? You guessed it right!

It’s the identity matrix.

So raising an n x n matrix to the power 0 results in an identity matrix I of shape n x n.

Let’s quickly check this in Python, using our previous matrix A.

C = np.linalg.matrix_power(A, 0)

print("A to power 0:\n{}, shape={}".format(C, C.shape))

Output:

Element-wise exponentiation

Just like how we could do element-wise multiplication of matrices, we can also do element-wise exponentiation i.e. raise each individual element of a matrix to some power.

This can be achieved in Python using standard exponent operator ‘**‘ – an example of operator overloading.

Again, we can provide a single constant power for all the elements in the matrix, or a matrix of powers for each element in the base matrix.

Let’s look at examples of both in Python:

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(3,3))

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

#constant power
B = A**2

print("A^2:\n{}, shape={}\n".format(B, B.shape))

powers = np.random.randint(0, 4, size=(3,3))

print("Power matrix:\n{}, shape={}\n".format(powers, powers.shape))

C = A ** powers

print("A^powers:\n{}, shape={}\n".format(C, C.shape))

Output:

Multiplication from a particular index

Suppose we have a 5 x 6 matrix A and another 3 x 3 matrix B. Obviously, we cannot multiply these two together, because of dimensional inconsistencies.

But what if we wanted to multiply a 3×3 submatrix in matrix A with matrix B while keeping the other elements in A unchanged?
For better understanding, refer to the following image:

matrix multiplication of A from indices 1,2 to 3,4 with B
This operation can be achieved in Python, by using matrix slicing to extract the submatrix from A, performing multiplication with B, and then writing back the result at relevant index in A.

Let’s see this in action.

import numpy as np

np.random.seed(42)

A = np.random.randint(0, 10, size=(5,6))

B = np.random.randint(0, 10, size=(3,3))

print("Matrix A:\n{}, shape={}\n".format(A, A.shape))

print("Matrix B:\n{}, shape={}\n".format(B, B.shape))

C = A[1:4,2:5] @ B

A[1:4,2:5] = C

print("Matrix A after submatrix multiplication:\n{}, shape={}\n".format(A, A.shape))

Output:

As you can see, only the elements at row indices 1 to 3 and column indices 2 to 4 have been multiplied with B and the same have been written back in A, while the remaining elements of A have remained unchanged.

Also, it’s unnecessary to overwrite the original matrix. We can also write the result in a new matrix, by first copying the original matrix to a new matrix and then writing the product at the position of the submatrix.

Matrix multiplication using GPU

We know that NumPy speeds up the matrix operations by parallelizing a lot of computations and making use of our CPU’s parallel computing capabilities.

However, modern-day applications need more than that. CPUs offer limited computation capabilities, and it does not suffice for the large number of computations that we need, typically in applications like deep learning.

That is where GPUs come into the picture. They offer large computation capabilities and excellent parallelized computation infrastructure, which helps us save a significant amount of time by doing hundreds of thousands of operations within fractions of seconds.

In this section, we will look at how we can perform matrix multiplication on a GPU, instead of a CPU and save a lot of time doing so.

NumPy does not offer the functionality to do matrix multiplications on GPU. So we must install some additional libraries that help us achieve our goal.

We will first install the ‘scikit-cuda‘ and ‘PyCUDA‘ libraries using pip install. These libraries help us perform computations on CUDA based GPUs. To install these libraries from your terminal, if you have a GPU installed on your machine.

pip install pycuda

pip install scikit-cuda

If you do not have a GPU on your machine, you can try out Google Colab notebooks, and enable GPU access, it’s free for use. Now we will write the code to generate two 1000×1000 matrices and perform matrix multiplication between them using two methods:

  1. Using NumPy’s ‘matmul()‘ method on a CPU
  2. Using scikit-cuda’s ‘linalg.mdot()‘ method on a GPU

In the second method, we will generate the matrices on a CPU, then we will store them on GPU (using PyCUDA’s ‘gpuarray.to_gpu()‘ method) before performing the multiplication between them. We will use the ‘time‘ module to compute the time of computation in both cases.

Using CPU

import numpy as np

import time

# generating 1000 x 1000 matrices
np.random.seed(42)

x = np.random.randint(0,256, size=(1000,1000)).astype("float64")

y = np.random.randint(0,256, size=(1000,1000)).astype("float64")

#computing multiplication time on CPU
tic = time.time()

z = np.matmul(x,y)

toc = time.time()

time_taken = toc - tic #time in s

print("Time taken on CPU (in ms) = {}".format(time_taken*1000))

Output:

On some old hardware systems, you may get a memory error, but if you are lucky, it will work in a long time (depends on your system).

Now, let us perform the same multiplication on a GPU and see how the time of computation differs between the two.

Using GPU

#computing multiplication time on GPU
linalg.init()

# storing the arrays on GPU
x_gpu = gpuarray.to_gpu(x)

y_gpu = gpuarray.to_gpu(y)

tic = time.time()

#performing the multiplication
z_gpu = linalg.mdot(x_gpu, y_gpu)

toc = time.time()

time_taken = toc - tic #time in s

print("Time taken on a GPU (in ms) = {}".format(time_taken*1000))

Output:

As we can see, performing the same operation on a GPU gives us a speed-up of 70 times as on CPU.
This was still a small computation. For large scale computations, GPUs give us speed-ups of a few orders of magnitude.

Conclusion

In this tutorial, we looked at how multiplication of two matrices takes place, the rules governing them, and how to implement them in Python.
We also looked at different variants of the standard matrix multiplication (and their implementation in NumPy) like multiplication of over 2 matrices, multiplication only at a particular index, or power of a matrix.

We also looked at element-wise computations in matrices such as element-wise matrix multiplication, or element-wise exponentiation.

Finally, we looked at how we can speed up the matrix multiplication process by performing them on a GPU.

Five Things You Must Consider Before ‘Developing an App’

Before you begin developing an app, it is worth taking the time to properly plan out your development cycle. From defining your intended feature set to load testing, the more work you do before you start coding, the quicker you will be able to progress through the actual development of your app.Below are five essential things to consider before developing your app. The more detailed your initial plans for your app, the smoother the entire development process will go. Before you even think about how to actually code your app, you need to establish exactly what it is going to do and why it is going to be doing it. If you want to develop an app just for the sake of it, this is a great way to teach yourself new skills. But if you are looking at developing an app with an eye to commercializing it, you need to know exactly what you are doing before you begin.

The Purpose Of Your App

When developing an app for your business, there should be a clear rationale for you doing so. If you are only developing an app because you feel like you are supposed to or because your competitors have beaten you to the punch, the result is almost definitely going to be underwhelming.

On the other hand, if you take the time beforehand to plan your app properly and seriously consider how you can provide real value to your users, you stand a much better chance of critical and commercial success.

Before you can make any detailed plans about what your app will look like and what it will do, you need to be clear with yourself about what its main purpose is.

The Intended Feature Set

Once you have defined the ultimate purpose of your app, you can then begin to think about what features you need to include to achieve it.

Laying out your feature set should be one of the first things you do when you are preparing to develop an app. The features you want to include will have an impact on every other part of the design process.

For example, when it comes to your user interface, you will want to choose something that makes it easy for a user to see and access all of the features your app offers.

Equally, when you are assigning coders to various tasks, knowing what features you are shooting for will enable you to delegate work appropriately. There is no sense in asking a coder to work on a feature that lies well outside of their skill set.

The Price Point

If you are developing an app for a business, most of the time it will be distributed for free. It is important to know upfront whether the app you are working on is going to be provided for free, whether it will cost money, or whether there is an associated subscription cost as the buyer want to save money in all cases.

The price point at which you intend to sell an app will determine how much money you can sink into its development. It will also have a significant impact on the way that the app is marketed.

Fortunately, it is possible for you to have the best of all worlds when it comes to pricing. Many app developers have realized the potential in offering a free version of the app that is funded through advertising alongside a premium version that includes no ads.

The Platform

Before you can properly plan out your app development, you need to establish exactly what platform you are going to be aiming for.

Even if you intend to make your app available on every mobile operating system possible, you will still need to prioritize. In the vast majority of cases, it will make more sense to build your app for one primary platform first and then go about converting it for other platforms.

If you are trying to develop an app for multiple different platforms simultaneously, you are much more likely to run into problems.

Not only this, but you will find yourself having to solve problems for multiple different platforms at once. It is far more efficient to develop for your primary platform and iron out all the kinks before moving on to the next one.

App Load Testing

Developing an app is much more involved than many people realize. Lots of people think that once you have written the code and compiled the binary, your app is done and dusted. On the contrary, it doesn’t matter how talented your coders are or how much regression testing you have undertaken, there is still a range of things that you need to test under specific circumstances.

Load testing is one of many tests that can be used to assess an app’s performance under certain circumstances. Specifically, load testing will tell you how well your app performs when the system running it is under a heavy load and most of its available resources are being used.

For an app that is entirely offline, it is the system resources of the device it is running on that matter.

However, if your app also has online features, the current load placed on your internet connection will also be a factor in determining performance. In this case, many developers use proxies to load test their servers. Some proxy providers offer easy to use options.

Planning is everything in app development. If you take the time beforehand to work out exactly what you are doing and why then you will find the whole process much easier.

NumPy loadtxt tutorial (Load data from files)

In a previous tutorial, we talked about NumPy arrays and we saw how it makes the process of reading, parsing and performing operations on numeric data a cakewalk. In this tutorial, we will discuss the NumPy loadtxt method that is used to parse data from text files and store them in an n-dimensional NumPy array. Then we can perform all sorts of operations on it that are possible on a NumPy array. np.loadtxt offers a lot of flexibility in the way we read data from a file by specifying options such as the data type of the resulting array, how to distinguish one data entry from the others through delimiters, skipping/including specific rows, etc. We’ll look at each of those ways in the following tutorial.

Specifying the file path

Let’s look at how we can specify the path of the file from which we want to read data.

We’ll use a sample text file for our code examples, which lists the weights (in kg) and heights (in cm) of 100 individuals, each on a row.

I will use various variants in this file for explaining different features of the loadtxt function.

Let’s begin with the simplest representation of the data in a text file. We have 100 lines (or rows) of data in our text file, each of which comprises 2 floating-point numbers separated by a space.

The first number on each row represents the weight and the second number represents the height of an individual.

Here’s a little glimpse from the file:

110.90 146.03
44.83 211.82
97.13 209.30
105.64 164.21

This file is stored as `weight_height_1.txt`.
Our task is to read the file and parse the data in a way that we can represent in a NumPy array.
We’ll import the NumPy package and call the loadtxt method, passing the file path as the value to the first parameter filePath.

import numpy as np

data = np.loadtxt("./weight_height_1.txt")

Here we are assuming the file is stored at the same location from where our Python code will run (‘./’ represents current directory). If that is not the case, we need to specify the complete path of the file (Ex: “C://Users/John/Desktop/weight_height_1.txt”)

We also need to ensure each row in the file has the same number of values.

The extension of the file can be anything other than .txt as long as the file contains text, we can also pass a generator instead of a file path (more on that later)

The function returns an n-dimensional NumPy array of values found in the text.

Here our text had 100 rows with each row having 2 float values, so the returned object data will be a NumPy array of shape (100, 2) with the float data type.

You can verify this by checking ‘shape’ and ‘dtype’ attribute of the returned data:

print("shape of data:",data.shape)

print("datatype of data:",data.dtype)

Output:

Specifying delimiters

A delimiter is a character or a string of characters that separates individual values on a line.

For example, in our earlier file, we had the values separated by a space, so in that case, the delimiter was a space character (” “).

However, some other files may have a different delimiter, for instance, CSV files generally use comma (“,”) as a delimiter. Another file may have a semicolon as a delimiter.

So we need our data loader to be flexible enough to identify such delimiters in each row and extract the correct values from them.

This can be achieved by passing our delimiter as a parameter to the np.loadtxt function.

Let us consider another file ‘weight_height_2.txt’, it has the same data content as the previous one, but this time the values in each row are separated by a comma:

110.90, 146.03
44.83, 211.82
97.13, 209.30

We’ll call the np.loadtxt function the same way as before, except that now we pass an additional parameter – ‘delimiter’:

import numpy as np

data = np.loadtxt("./weight_height_2.txt", delimiter = ",")

This function will return the same array as before.

  • In the previous section, we did not pass delimiter parameter value because np.loadtxt() expects space “ “ to be the default delimiter
  • If the values on each row were separated by a tab, in that case, the delimiter would be specified by using the escape character “\t”

You can verify the results again by checking the shape of the data array and also printing the first few rows:

print("shape of array", data.shape)

print("First 5 rows:\n", data[:5])

Output:

Dealing with 2 delimiters

Now there may be a situation where there are more than 1 delimiters in a file.

For example, let’s imagine each of our lines contained a 3rd value representing the date of birth of the individual in dd-mm-yyyy format

110.90, 146.03, 3-7-1981
44.83, 211.82, 1-2-1986
97.13, 209.30, 14-2-1989

Now suppose we want to extract the dates, months and years as 3 different values into 3 different columns of our NumPy array. So should we pass “,” as the delimiter or should we pass “-”?

We can pass only 1 value to the delimiter parameter in the np.loadtxt method!

No need to worry, there is always a workaround. Let’s use a third file ‘./weight_height_3.txt’ for this example

We’ll use a naive approach first, which has the following steps:

  1. read the file
  2. eliminate one of the delimiters in each line and replace it with one common delimiter (here comma)
  3. append the line into a running list
  4. pass this list of strings to the np.loadtxt function instead of passing a file path.

Let’s write the code:

#reading each line from file and replacing "-" by ","
with open("./weight_height_3.txt") as f_input:

text = [l.replace("-", ",") for l in f_input]

#calling the loadtxt method with “,“ as delimiter
data = np.loadtxt(text, delimiter=",")

  • Note that we are passing a list of strings as input and not a file path.
  • When calling the function we still pass the delimiter parameter with the value “,” as we’ve replaced all instances of the second delimiter ‘-’ by a comma.
  • The returned NumPy array should now have 5 columns

You can once again validate the results by printing the shape and the first five lines:

print("Shape of data:", data.shape)

print("First five rows:\n",data[:5])

Output:

Notice how we have 3 additional columns in each row indicating the date, month and year of birth

Also notice the new values are all floating-point values; however date, month or year make more sense as integers!
We’ll look at how to handle such data type inconsistencies in the coming section.

A general approach for multiple delimiters

In this section, we will look at a general approach for working with multiple delimiters.

Also, we’ll learn how we can use generators instead of file paths – a more efficient solution for multiple delimiters, than the one we discussed in the previous section.

The problem with reading the entire file at once and storing them as a list of strings is that it doesn’t scale well. For instance, if there is a file with a million lines, storing them in a list all at once is going to consume unnecessary additional memory.

Hence we will use generators to get rid of any additional delimiter.
A generator ‘yields’ us a sequence of values on the fly i.e it will read the lines of a file as required instead of reading them all at once

So let’s first define a generator function that takes in a file path and a list of delimiters as a parameter.

def generate_lines(filePath, delimiters=[]):

with open(filePath) as f:

for line in f:

line = line.strip() #removes newline character from end

for d in delimiters:

line =line.replace(d, " ")

yield line

Here we are going through each of the delimiters one by one in each line and replacing them by a blank space ” ” which is the default delimiter in np.loadtxt function

We will now call this generator function and pass the returned generator object to the np.loadtxt method in place of the file path.

gen = generate_lines("./weight_height_3.txt", ["-",","])

data = np.loadtxt(gen)

Note that we did not need to pass any additional delimiter parameter, as our generator function replaced all instances of the delimiters in the passed list by a space, which is the default delimiter.

We can extend this idea and specify as many delimiters as needed.

Specifying the data type

Unless specified otherwise, the np.loadtxt function of the NumPy package assumes the values in the passed text file to be floating-point values by default.

So if you pass a text file that has characters other than numbers, the function will throw an error, stating it was expecting floating-point values.

We can overcome this by specifying the data type of the values in the text file using the datatypeparameter.

In the previous example, we saw the date, month and year were being interpreted as floating-point values, however, we know that these values can never exist in decimal form.

Let’s look at a new file ‘./weight_height_4.txt’ which has only 1 column for the date of birth of individuals in the dd-mm-yyyy format:

13-2-1991
17-12-1990
18-12-1986

So we’ll call the loadtxt method with “-” as the delimiter:

data = np.loadtxt("./weight_height_4.txt", delimiter="-")

print(data[:3])

print("datatype =",data.dtype)

If we look at the output of the above lines of code, we’ll see that each of the 3 values has been stored as floating-point values by default and the data type of the array is ‘float64’

We can alter this behavior by passing the value ‘int’ to the ‘dtype’ parameter. This will ask the function to store the extracted values as integers, and hence the data type of the array will also be int.

data = np.loadtxt("./weight_height_4.txt", delimiter="-", dtype="int")

print(data[:3])

print("datatype =",data.dtype)

Output:

But what if there are columns with different data types?

Let’s say we have the first two columns having float values and the last column having integer values.

In that case, we can pass a comma-separated datatype string specifying the data type of each column (in order of their existence) to the dtype parameter.

However, in such a case the function will return a NumPy array of tuples of values since a NumPy array as a whole can have only 1 data type

Let’s try this on ‘weight_height_3.txt’ file where the first two columns (weight, height) had float values and the last 3 values (date, month, year) were integers:

Output:

Ignoring headers

In some cases (especially CSV files), the first line of the text file may have ‘headers’ describing what each column in the following rows represents. While reading data from such text files, we may want to ignore the first line because we cannot (and should not) store them in our NumPy array.

In such a case, we can use the ‘skiprows’ parameter and pass the value 1, asking the function to ignore the first 1 line(s) of the text file.

Let’s try this on a CSV file – ‘weight_height.csv’:

Weight (in Kg), Height (in cm)
73.847017017515,241.893563180437
68.7819040458903,162.310472521300
74.1101053917849,212.7408555565

Now we want to ignore the header line i.e the first line of the file:

data = np.loadtxt("./weight_height.csv", delimiter=",", skiprows=1)

print(data[:3])

Output:

Likewise, we can pass any positive integer n to the skiprows parameter asking to ignore first n rows from the file.

Ignoring the first column

Sometimes, we may also want to skip the first column because we are not interested in it. For example, if our text file had the first column as “gender”, and if we don’t need to include the values of this column when extracting the data, we need a way to ask the function to do the same.

We do not have a skipcols parameter like skiprows in np.loadtxt function, using which, we could express this need. However, np.loadtxt has another parameter called ‘usecols’ where we specify the indices of the columns to be retained.

So if we want to skip the first column, we can simply supply the indices of all the columns except the first (remember indexing begins at zero)

Enough talking, let’s get to work!

Let’s look at the content of a new file ‘weight_height_5.txt’ which has an additional gender column that we want to ignore.

Male, 110.90, 146.03
Male, 44.83, 211.82


Female, 78.67, 158.74
Male, 105.64, 164.21

We’ll first determine the number of columns in the file from the first line and then pass a range of column indices excluding the first one:

with open("./weight_height_5.txt") as f:
#determining number of columns from the first line of text

n_cols = len(f.readline().split(","))

data = np.loadtxt("./weight_height_5.txt", delimiter=",",usecols=np.arange(1, n_cols))

print("First five rows:\n",data[:5])

Here we are supplying a range of values beginning from 1 (second column) and extending up to n_cols (the last column)

Output:

We can generalize the use of the usecols parameter by passing a list of indices of only those columns that we want to retain.

Load first n rows

Just as we can skip the first n rows using the skiprows parameter, we can also choose to load only the first n rows and skip the rest. This can be achieved using the max_rows parameter of the np.loadtxt method.

Let us suppose that we want to read only the first 10 rows from the text file ‘weight_height_2.txt’. We’ll call the np.loadtxt method along with the max_rows parameter and pass the value 10.

data = np.loadtxt("./weight_height_2.txt", delimiter=",",max_rows = 10)

print("Shape of data:",data.shape)

Output:

As we can see, the returned NumPy array has only 10 rows which are the first 10 rows of the text file.

If we use the max_rows parameter along with skiprowsparameter, then the specified number of rows will be skipped and next n rows will be extracted where n is the value we pass to max_rows.

Load specific rows

If we want the np.loadtxt function to load only specific rows from the text file, no parameter supports this feature.

However, we can achieve this by defining a generator that accepts row indices and returns lines at those indices. We’ll then pass this generator object to our np.loadtxt method.

Let’s first define the generator:

def generate_specific_rows(filePath, row_indices=[]):

with open(filePath) as f:

# using enumerate to track line no.
for i, line in enumerate(f):

#if line no. is in the row index list, then return that line
if i in row_indices:

yield line

Let’s now use the np.loadtxt function to read the 2nd, 4th and 100th line in the file ‘weight_height_2.txt

gen = generate_specific_rows("./weight_height_2.txt",row_indices = [1, 3, 99])

data = np.loadtxt(gen, delimiter=",")

print(data)

This should return a NumPy array having 3 rows and 2 columns:

Skip the last row

If you want to exclude the last line of the text file, you can achieve this in multiple ways. You can either define another generator that yields lines one by one and stops right before the last one, or you can use an even simpler approach – just figure out the number of lines in the file, and pass 1 less than that count to the max_rows parameter.

But how will you figure out the number of lines?
Follow along!

with open("./weight_height_2.txt") as f:

n = len(list(f))

print("n =", n)

Now n contains the number of lines present in `weight_height_2.txt` file, that value should be 100.

We will now read the text file as we used to, using the np.loadtxt method along with the max_rows parameter with value n – 1.

data = np.loadtxt("./weight_height_2.txt", delimiter=",",max_rows=n - 1)

print("data shape =",data.shape)

Output:

As we can see, the original text file had 100 rows, but when we read data from the file, it’s shape is (99, 2) since it skipped the last row from the file.

Skip specific columns

Suppose you wanted to ignore some of the columns while loading data from a text file by specifying the indices of such columns.

While the np.loadtxt method provides a parameter to specify which columns to retain (usecols), it doesn’t offer a way to do the opposite i.e specify which columns to skip. However, we can always find a workaround!

We shall first define the indices of columns to be ignored, and then using them we will derive the list of indices to be retained as the two sets would be mutually exclusive.

We will then pass this derived indices list to the usecols parameter.

Here is pseudocode for the entire process:

  1. Find the number of columns in the file n_cols (explained in an earlier section)
  2. Define the list of indices to be ignored
  3. Create a range of indices from 0 to n_cols, and eliminate the indices of step 2 from this range
  4. Pass this new list to usecols parameter in np.loadtxt method

Let’s create a wrapper function loadtext_without_columns that implements all the above steps:

def loadtext_without_columns(filePath, skipcols=[], delimiter=","):

with open(filePath) as f:

n_cols = len(f.readline().split(delimiter))

#define a range from 0 to n_cols
usecols = np.arange(0, n_cols)

#remove the indices found in skipcols
usecols = set(usecols) - set(skipcols)

#sort the new indices in ascending order
usecols = sorted(usecols)

#load the file and retain indices found in usecols
data = np.loadtxt(filePath, delimiter = delimiter, usecols = usecols)

return data

To test our code, we will work with a new file `weight_height_6.txt` which has 5 columns – the first two columns indicate width and height and the remaining 3 indicate the date, month and year of birth of the individuals.

All the values are separated by a single delimiter – comma:

110.90, 146.03, 3,7,1981
44.83, 211.82, 1,2,1986
97.13, 209.30, 14,2,1989


105.64, 164.21, 3,6,2000

Suppose we were not interested in the height and the date of birth of the individual, and so we wanted to skip the columns at positions 1 and 2.

Let’s call our wrapper function specifying our requirements:

data = loadtext_without_columns("./weight_height_6.txt",skipcols = [1, 2], delimiter = ",")

# print first 5 rows
print(data[:5])

Output:

We can see that our wrapper function only returns 3 columns – weight, month and year. It has ensured that the columns we specified have been skipped!

Load 3D arrays

So far we’ve been reading the contents of the file as a 2D NumPy array. This is the default behavior of the np.loadtxt method, and there’s no additional parameter that we can specify to interpret the read data as a 3D array.

So the simplest approach to solve this problem would be to read the data as a NumPy array and use NumPy’s reshape method to reshape the data in any shape of any dimension that we desire.

We just need to be careful that if we want to interpret it as a multidimensional array, we should make sure it is stored in the text file in an appropriate manner and that after reshaping the array, we’d get what we actually desired.

Let us take an example file – ‘weight_height_7.txt’.

This is the same file as ‘weight_height_2.txt’. The only difference is that this file has 90 rows, and each 30-row block represents a different section or class to which individuals belong.

So there are a total of 3 sections (A, B and C) – each having 30 individuals whose weights and heights are listed on a new row.

The section names are denoted with a comment just before the beginning of each section (you can check this at lines 1, 32 and 63).

The comment statements begin with ‘#’ and these lines are ignored by np.loadtxt when reading the data. We can also specify any other identifier for comment lines using the parameter ‘comments’

Now when you read this file, and print its shape, it would display (90,2) because that is how np.loadtxt reads the data – it arranges a multi-row data into 2D arrays.

But we know that there is a logical separation between each group of 30 individuals, and we would want the shape to be (3, 30, 2) – where the first dimension indicates the sections, the second one represents each of the individuals in that section and the last dimension indicates the number of values associated to each of these individuals (here 2 for weight & height).

Using NumPy reshape method

So we want our data to be represented as a 3D array.

We can achieve this by simply reshaping the returned data using NumPy’s reshape method.

data = np.loadtxt("./weight_height_7.txt",delimiter=",")

print("Current shape = ",data.shape)

Settingsdata = data.reshape(3,30,2)

print("Modified shape = ",data.shape)

print("fifth individual of section B - weight, height =",data[1,4,:])

Output:

Notice how we are printing the details of a specific individual using 3 indices

The returned result belongs to the 5th individual of section B – this can be validated from the text:

#section B
100.91, 155.55
72.93, 150.38
116.68, 137.15
86.51, 172.15
59.85, 155.53

Comparison with alternatives

While numpy.loadtxt is an extremely useful utility for reading data from text files, it is not the only one!

There are many alternatives out there that can do the same task as np.loadtxt, many of these are better than np.loadtxt in many aspects. Let’s briefly look at 3 such alternative functions.

numpy.genfromtxt

  1. This is the most discussed and the most used method alongside np.loadtxt
  2. There’s no major difference between the two, the only one that stands out is np.genfromtxt’s ability to smoothly handle missing values.
  3. In fact, NumPy’s documentation describes np.loadtxt as “an equivalent function (to np.genfromtxt) when no data is missing.
  4. So the two are almost similar methods, except that np.genfromtxt can do more sophisticated processing of the data in a text file.

numpy.fromfile

  1. np.fromfile is commonly used when working with data stored in binary files, with no delimiters.
  2. It can read plain text files but does so with a lot of issues (go ahead and try reading the files we discussed using np.fromfile)
  3. While it is faster in execution time than np.loadtxt, but it is generally not a preferred choice when working with well-structured data in a text file.
  4. Besides NumPy’s documentation mentions np.loadtxt as a ‘more flexible (than np.fromfile) way of loading data from a text file.

pandas.read_csv

  1. pandas.read_csv is the most popular choice of Data Scientists, ML Engineers, Data Analysts, etc. for reading data from text files.
  2. It offers way more flexibility than np.loadtxt or np.genfromtxt.
  3. Although you cannot pass a generator to pandas.read_csv as we did.
  4. In terms of speed of execution, however, pandas.read_csv do better than np.loadtxt

Handling Missing Values

As discussed in our section comparing np.loadtxt with other options, np.genfromtxt handles missing values by default. We do not have any direct way of handling missing values in np.loadtxt

Here we’ll look at an indirect (and a slightly sophisticated) way of handling missing values with the np.loadtxt method.

The converters parameter:

  • np.loadtxt has a converters parameter that is used to specify the preprocessing (if any) required for each of the columns in the file.
  • For example, if the text file stores the height column in centimeters and we want to store them as inches, we can define a converter for the heights column.
  • The converters parameter accepts a dictionary where the keys are column indices and the values are methods that accept the column value, ‘convert’ it and return the modified value.

How can we use converters to handle missing values?

  • We need to first decide the default datatype i.e the value to be used to fill in the positions where the actual values are missing. Let’s say we want to fill in the missing height and weight values with 0, so our fill_value will be 0.
  • Next, we can define a converter for each column in the file, which checks if there is some value or an empty string in that column and if it’s an empty string, it will fill it with our fill_value.
  • To do this, we’ll have to find the number of columns in the text file, and we have already discussed how to achieve this in an earlier section.

We’ll use the file ‘weight_height_8.txt’ which is the same as ‘weight_height_2.txt’ but has several missing values.

, 146.03
44.83, 211.82
97.13,
69.87, 207.73
, 158.87
99.25, 195.41

Let’s write the code to fill in these missing values’ positions with 0.

# finding number of columns in the file
with open("./weight_height_8.txt") as f:

n_cols = len(f.readline().split(","))

print("Number of columns", n_cols)

# defining converters for each of the column (using 'dictionary
# comprehension') to fill each missing value with fill_value

fill_value = 0

converters = {i: lambda s: float(s.strip() or fill_value) for i in range(2)}

data = np.loadtxt("./weight_height_8.txt", delimiter=",",converters = converters)

print("data shape =",data.shape)

print("First 5 rows:\n",data[:5])

Output:

The missing height and weight values have been correctly replaced with a 0. No magic!

Conclusion

numpy.loadtxt is undoubtedly one of the most standard choices for reading a well-structured data stored in a text file. It offers us great flexibility in choosing various options for specifying the way we want to read the data, and wherever it doesn’t – remember there’s always a workaround!

Caesar Cipher in Python (Text encryption tutorial)

Cryptography deals with encrypting or encoding a piece of information (in a plain text) into a form that looks gibberish and makes little sense in ordinary language. This encoded message(also called ciphertext) can then be decoded back into a plain text by the intended recipient using a decoding technique (often along with a private key) communicated to the end-user. Caesar Cipher is one of the oldest encryption technique that we will focus on in this tutorial, and will implement the same in Python. Although Caesar Cipher is a very weak encryption technique and is rarely used today, we are doing this tutorial to introduce our readers, especially the newcomers, to encryption. Consider this as the ‘Hello World’ of Cryptography.

What is Caesar Cipher?

Caesar Cipher is a type of substitution cipher, in which each letter in the plain text is replaced by another letter at some fixed positions from the current letter in the alphabet.

For example, if we shift each letter by 3 positions to the right, each of the letters in our plain text will be replaced by a letter at 3 positions to the right of the letter in the plain text. Let us see this in action – let’s encrypt the text “HELLO WORLD” using a right shift of 3.

So the letter H will be replaced by K, E will be replaced by H, and so on. The final encrypted message for HELLO WORLD will be KHOOR ZRUOG. That gibberish doesn’t make sense, does it?

Note that the letters on the edge i.e. X, Y, Z wrap around and are replaced by A, B, C respectively, in case of the right shift. Similarly the letters in the beginning – A, B, C, etc. will be wrapped around in case of left shifts.

The Caesar Cipher encryption rule can be expressed mathematically as:

c = (x + n) % 26

Where c is the encoded character, x is the actual character, and n is the number of positions we want to shift the character x by. We’re taking mod with 26 because there are 26 letters in the English alphabet.

Caesar Cipher in Python

Before we dive into defining the functions for the encryption and decryption process of Caesar Cipher in Python, we’ll first look at two important functions that we’ll use extensively during the process – chr() and ord().
It is important to realize that the alphabet as we know them is stored differently in a computer’s memory. The computer doesn’t understand any of our English language’s alphabet or other characters by itself.

Each of these characters is represented in computer memory using a number called ASCII code (or its extension – the Unicode) of the character, which is an 8-bit number and encodes almost all the English language’s characters, digits, and punctuations.
For instance, the uppercase ‘A’ is represented by the number 65, ‘B’ by 66, and so on. Similarly, lowercase characters’ representation begins with the number 97.

As the need to incorporate more symbols and characters of other languages arose, the 8 bit was not sufficient, so a new standard – Unicode – was adopted, which represents all the characters used in the world using 16 bits.
ASCII is a subset of Unicode, so the ASCII encoding of characters remains the same in Unicode. That means ‘A’ will still be represented using the number 65 in Unicode.
Note that the special characters like space ” “, tabs “\t”, newlines “\n”, etc. are also represented in memory by their Unicode.

We’ll look at 2 built-in functions in Python that are used to find the Unicode representation of a character and vice-versa.

The ord() function

The ord() method is used to convert a character to its numeric representation in Unicode. It accepts a single character and returns the number representing its Unicode. Let’s look at an example.

c_unicode = ord("c")

A_unicode = ord("A")

print("Unicode of 'c' =", c_unicode)

print("Unicode of 'A' =", A_unicode)

Output:

The chr() function

Just like how we could convert a character into its numeric Unicode using ord() method, we do the inverse i.e. find the character represented by a number using chr() method.
The chr() method accepts a number representing the Unicode of a character and returns the actual character corresponding to the numeric code. Let’s first look at a few examples:

character_65 = chr(65)

character_100 = chr(100)

print("Unicode 65 represents", character_65)

print("Unicode 100 represents", character_100)

character_360 = chr(360)

print("Unicode 360 represents", character_360)

Output:

Notice how the German letter Ü (U umlaut) is also represented in Unicode, by the number 360.

We can also apply a chained operation(ord followed by chr) to get the original character back.

c = chr(ord("Ũ"))

print(c)

Output: Ũ

Encryption for Capital Letters

Now that we understand the 2 fundamental methods we’ll use, let’s implement the encryption technique for capital letters in Python. We shall encrypt only the uppercase characters in the text and will leave the remaining ones unchanged.
Let’s first look at the step-by-step process of encrypting the capital letters:

  1. Define the shift value i.e. the number of positions we want to shift from each character.
  2. Iterate over each character of the plain text:
    1. If the character is upper-case:
      1. Calculate the position/index of the character in the 0-25 range.
      2. Perform the positive shift using the modulo operation.
      3. Find the character at the new position.
      4. Replace the current capital letter by this new character.
    2. Else, If the character is not upper-case, keep it with no change.

Let us now look at the code:

shift = 3 # defining the shift count

text = "HELLO WORLD"

encryption = ""

for c in text:

# check if character is an uppercase letter
if c.isupper():

# find the position in 0-25
c_unicode = ord(c)

c_index = ord(c) - ord("A")

# perform the shift
new_index = (c_index + shift) % 26

# convert to new character
new_unicode = new_index + ord("A")

new_character = chr(new_unicode)

# append to encrypted string
encryption = encryption + new_character

else:

# since character is not uppercase, leave it as it is
encryption += c

print("Plain text:",text)

print("Encrypted text:",encryption)

Output:

As we can see the encrypted text for “HELLO WORLD” is “KHOOR ZRUOG”, and it matches with the one we arrived at manually in the Introduction section
Also notice that the space character has not been encrypted, and it continues to be a space in the encrypted version.

Decryption for Capital Letters

Now that we’ve figured out the encryption for plain text capital letters using Ceaser Cipher, let’s look at how we will decrypt the ciphertext into plain text.

Earlier we looked at the mathematic formulation of the encryption process. Let’s now check out the same for the decryption process.

x = (c - n) % 26

The meaning of the notations remain the same as in the previous formula
If any value becomes negative after subtraction, the same can be taken care of by the modulo operator and the values will be wrapped around

Let us look at the step-by-step implementation of the decryption process, which will be more or less the reverse of the encryption:

  • Define the number of shifts
  • Iterate over each character in the encrypted text:
    • If the character is an uppercase letter:
      1. Calculate the position/index of the character in the 0-25 range.
      2. Perform the negative shift using the modulo operation.
      3. Find the character at the new position.
      4. Replace the current encrypted letter by this new character (which will also be an uppercase letter).
      5. Else, if the character is not capital, keep it unchanged.

Let’s write the code for the above procedure:

shift = 3 # defining the shift count

encrypted_text = "KHOOR ZRUOG"

plain_text = ""

for c in encrypted_text:

# check if character is an uppercase letter
if c.isupper():

# find the position in 0-25
c_unicode = ord(c)

c_index = ord(c) - ord("A")

# perform the negative shift
new_index = (c_index - shift) % 26

# convert to new character
new_unicode = new_index + ord("A")

new_character = chr(new_unicode)

# append to plain string
plain_text = plain_text + new_character

else:

# since character is not uppercase, leave it as it is
plain_text += c

print("Encrypted text:",encrypted_text)

print("Decrypted text:",plain_text)

Output:

Notice how we have successfully recovered the original text “HELLO WORLD” from its encrypted form.

Encrypting numbers and punctuation

Now that we’ve seen how we can encode and decode capital letters of the English alphabet using Caesar Cipher, it begs an important question – What about the other characters?
What about the numbers? What about the special characters and the punctuation?

Well, the original Caesar Cipher algorithm was not supposed to deal with anything other than the 26 letters of the alphabet – either in uppercase or lowercase.
So a typical Caesar Cipher would not encrypt punctuation or numbers and would convert all the letters to either lowercase or uppercase and encode only those characters.

But we can always extend an existing good solution and tweak them to suit our needs – that’s true for any kind of challenge in software engineering.
So we’ll try to encode uppercase and lowercase characters the way we did in the previous section, we’ll ignore the punctuations for now, and then we’ll also encode the numbers in the text.

For numbers, we can do the encryption in one of the two ways:

  1. Shift the digit value by the same amount as you shift the letters of the alphabet, i.e. for a shift of 3 – digit 5 becomes 8, 2 becomes 5, 9 becomes 2, and so on.
  2. Make the numbers part of the alphabet, i.e. z or Z will be followed by 0,1,2… up to 9 and this time our divider for modulo operation will be 36 instead of 26.

We’ll implement our solution using the first strategy. Also this time, we’ll implement our solution as a function that accepts the shift value (which serves as the key in Caesar Cipher) as a parameter.
We’ll implement 2 functions – cipher_encrypt() and cipher_decrypt()
Let’s get our hands dirty!

The solution

# The Encryption Function
def cipher_encrypt(plain_text, key):

encrypted = ""

for c in plain_text:

if c.isupper(): #check if it's an uppercase character

c_index = ord(c) - ord('A')

# shift the current character by key positions
c_shifted = (c_index + key) % 26 + ord('A')

c_new = chr(c_shifted)

encrypted += c_new

elif c.islower(): #check if its a lowecase character

# subtract the unicode of 'a' to get index in [0-25) range
c_index = ord(c) - ord('a')

c_shifted = (c_index + key) % 26 + ord('a')

c_new = chr(c_shifted)

encrypted += c_new

elif c.isdigit():

# if it's a number,shift its actual value
c_new = (int(c) + key) % 10

encrypted += str(c_new)

else:

# if its neither alphabetical nor a number, just leave it like that
encrypted += c

return encrypted

# The Decryption Function
def cipher_decrypt(ciphertext, key):

decrypted = ""

for c in ciphertext:

if c.isupper():

c_index = ord(c) - ord('A')

# shift the current character to left by key positions to get its original position
c_og_pos = (c_index - key) % 26 + ord('A')

c_og = chr(c_og_pos)

decrypted += c_og

elif c.islower():

c_index = ord(c) - ord('a')

c_og_pos = (c_index - key) % 26 + ord('a')

c_og = chr(c_og_pos)

decrypted += c_og

elif c.isdigit():

# if it's a number,shift its actual value
c_og = (int(c) - key) % 10

decrypted += str(c_og)

else:

# if its neither alphabetical nor a number, just leave it like that
decrypted += c

return decrypted

Now that we’ve defined our 2 functions, let’s first use the encryption function to encrypt a secret message a friend is sharing via text message to his buddy.

plain_text = "Mate, the adventure ride in Canberra was so much fun, We were so drunk we ended up calling 911!"

ciphertext = cipher_encrypt(plain_text, 4)

print("Plain text message:\n", plain_text)

print("Encrypted ciphertext:\n", ciphertext)

Output:

Notice how everything except punctuation and spaces has been encrypted.

Now let us look at a ciphertext that Colonel Nick Fury was sending on his pager: ‘Sr xli gsyrx sj 7, 6, 5 – Ezirkivw Ewwiqfpi!
Turns out it’s Caesar’s ciphertext and fortunately, we got our hands on the key to this ciphertext!
Let’s see if we can unearth the hidden message.

ciphertext = "Sr xli gsyrx sj 7, 6, 5 - Ezirkivw Ewwiqfpi!"

decrypted_msg = cipher_decrypt(ciphertext, 4)

print("The cipher text:\n", ciphertext)

print("The decrypted message is:\n",decrypted_msg)

Output:

Way to go, Avengers!

Using a lookup table

At this stage, we have understood the encryption and decryption process of the Caesar Cipher, and have implemented the same in Python.

Now we will look at how it can be made more efficient and more flexible.
Specifically, we’ll focus on how we can avoid the repeated computations of the shifted positions for each letter in the text during the encryption and decryption process, by building a lookup table ahead of time.

We’ll also look at how we can accommodate any set of user-defined symbols and not just the letters of the alphabet in our encryption process.
We’ll also merge the encryption and decryption process into 1 function and will accept as a parameter which of the two processes the user wants to execute.

What is a lookup table?

A lookup table is simply a mapping of the original characters and the characters they should translate to in an encrypted form.
So far we have been iterating over each of the letters in the string and computing their shifted positions.
This is inefficient because our character set is limited, and most of them occur more than once in the string.
So computing their encrypted equivalence each time they occur is not efficient, and it becomes costly if we are encrypting a very long text with hundreds of thousands of characters in it.

We can avoid this by computing the shifted positions of each of the characters in our character set only once, before starting the encryption process.
So if there are 26 uppercase and 26 lowercase letters, we’d need only 52 computations once and some space in memory to store this mapping.
Then during the encryption and decryption process, all we’d have to do is perform a ‘lookup’ in this table – an operation that is faster than performing a modulo operation each time.

Creating a lookup table

Python’s string module provides an easy way not just to create a lookup table, but also to translate any new string based on this table.

Let’s take an example where we want to create a table of the first five lowercase letters and their indices in the alphabet.
We’d then use this table to translate a string where each of the occurrences of ‘a’, ‘b’, ‘c’, ‘d’ and ‘e’ are replaced by ‘0’, ‘1’, ‘2’, ‘3’ and ‘4’ respectively; and the remaining characters are untouched.

We will use the maketrans() function of the str module to create the table.
This method accepts as its first parameter, a string of characters for which translation is needed, and another string parameter of the same length that contains the mapped characters for each character in the first string.

Let’s create a table for a simple example.

table = str.maketrans("abcde", "01234")

The table is a Python dictionary, that has the characters’ Unicode values as keys, and their corresponding mappings as values.
Now that we have our table ready, we can translate strings of any length using this table.
Fortunately, the translation is also handled by another function in the str module, called translate.

Let’s use this method to convert our text using our table.

text = "Albert Einstein, born in Germany, was a prominent theoretical physicist."

translated = text.translate(table)

print("Original text:/n", text)

print("Translated text:/n", translated)

Output:

As you can see, each instance of the first 5 lowercase letters have been replaced by their relative indices

We’ll now use the same technique to create a lookup table for Caesar Cipher, based on the key provided.

Implementing the encryption

Let’s create a function caesar_cipher() that accepts a string to be encrypted/decrypted, the ‘character set’ showing which characters in the string should be encrypted (this will default to lowercase letters),
the key, and a boolean value showing if decryption has performed or otherwise(encryption).

import string

def cipher_cipher_using_lookup(text, key, characters = string.ascii_lowercase, decrypt=False):

if key < 0:

print("key cannot be negative")

return None

n = len(characters)

if decrypt==True:

key = n - key

table = str.maketrans(characters, characters[key:]+characters[:key])

translated_text = text.translate(table)

return translated_text

Now that’s one powerful function out there!

The whole shifting operation has been reduced to a slicing operation.
Also, we are using string.ascii_lowercase attribute – it is a string of characters from ‘a’ to ‘z’.
Another important feature we’ve achieved here is that the same function achieves both encryption and decryption, this can be done by changing the value of the ‘key’ parameter.
The slicing operation along with this new key ensures the character set has been left-shifted – something we do in the decryption of a right shift Caesar ciphertext.

Let’s validate if this works by using an earlier example.
We’ll encrypt only capital letters of the text and will supply the same to the ‘characters’ parameter.
We’ll encrypt the text: “HELLO WORLD! Welcome to the world of Cryptography!”

text = "HELLO WORLD! Welcome to the world of Cryptography!"

encrypted = cipher_cipher_using_lookup(text, 3, string.ascii_uppercase, decrypt=False)

print(encrypted)

Output:

Check how the “KHOOR ZRUOG” part matches to encryption of “HELLO WORLD” with key 3 in our first example.
Also, note that we are specifying the character set to be uppercase letters using string.ascii_uppercase

We can check if decryption works properly, by using the same encrypted text we got in our previous result.
If we can recover our original text back, that means our function works perfectly.

text = "KHOOR ZRUOG! Zelcome to the world of Fryptography!"

decrypted = cipher_cipher_using_lookup(text, 3, string.ascii_uppercase, decrypt=True)

print(decrypted)

Output:

Notice how we have set the ‘decrypt’ parameter in our function to True.
Since we have recovered our original text back, it’s a sign our encryption-decryption algorithm using a lookup table is works well!

Let’s now see if we can extend the character set to include not just lowercase/uppercase characters but also digits and punctuations.

character_set = string.ascii_lowercase + string.ascii_uppercase + string.digits + " "+ string.punctuation

print("Extended character set:\n", character_set)

plain_text = "My name is Dave Adams. I am living on the 99th street. Please send the supplies!"

encrypted = cipher_cipher_using_lookup(plain_text, 5, character_set, decrypt=False)

print("Plain text:\n", plain_text)

print("Encrypted text:\n", encrypted)

Output:

Here we included all the characters we discussed so far (including space character) in the character set to be encoded.
As a result, everything (even the spaces) in our plain text has been replaced by another symbol!
The only difference here is that the wrap-around doesn’t happen individually for lowercase or uppercase characters, but it happens as a whole for the entire character set.
That means ‘Y’ with a shift of 3 will not become ‘B’, but will be encoded to ‘1’.

Negative shift

So far we’ve been doing ‘positive’ shifts or ‘right shifts’ of the characters in the encryption process. And the decryption process for the same involved doing a ‘negative’ shift or ‘left shift’ of the characters.
But what if we want to perform the encryption process with a negative shift? Would our encryption-decryption algorithm change?
Yes, it will, but only slightly. The only change we need for a left shift is to make the sign of the key negative, the rest of the process shall remain the same and will achieve the result of a left shift in encryption and a right shift in the decryption process.

Let us try this by modifying our previous function by adding one more parameter – ‘shift_type’ to our function cipher_cipher_using_lookup().

import string

def cipher_cipher_using_lookup(text, key, characters = string.ascii_lowercase, decrypt=False, shift_type="right"):

if key < 0:

print("key cannot be negative")

return None

n = len(characters)

if decrypt==True:

key = n - key

if shift_type=="left":

# if left shift is desired, we simply inverse they sign of the key
key = -key

table = str.maketrans(characters, characters[key:]+characters[:key])

translated_text = text.translate(table)

return translated_text

Let us test this modified method on a simple text.

text = "Hello World !"

encrypted = cipher_cipher_using_lookup(text, 3, characters = (string.ascii_lowercase + string.ascii_uppercase), decrypt = False, shift_type="left")

print("plain text:", text)

print("encrypted text with negative shift:",encrypted)

Output:

Notice how each of the characters in our plain text has been shifted to the left by 3 positions.
Let’s now check the decryption process using the same string.

text = "Ebiil Tloia !"

decrypted = cipher_cipher_using_lookup(text, 3, characters = (string.ascii_lowercase + string.ascii_uppercase), decrypt = True, shift_type="left")

print("encrypted text with negative shift:", text)

print("recovered text:",decrypted)

Output:

So we could encrypt and decrypt a text using a lookup table and a negative key.

File encryption

In this section, we’ll look at using Caesar Cipher to encrypt a file.
Not that it’s a great choice of encryption (we’ll soon learn why) but it helps you understand the general process of how files are encrypted using any of the algorithms.

Note that we can only encrypt plain text files, and not binary files because we know the character set for plain text files.
So, you can encrypt a file using one of the following 2 approaches:

  1. Read the whole file into a string, encrypt the string and dump it into another file.
  2. Iteratively read the file one line at a time, encrypt the line, and write it to another text file.

We’ll go with the second approach because the first one is feasible only for small files whose content can fit into memory easily.
So let’s define a function that accepts a file and encrypts it using Caesar Cipher with a right shift of 3. We’ll use the default character set of lower case letters.

def fileCipher(fileName, outputFileName, key = 3, shift_type = "right", decrypt=False):

with open(fileName, "r") as f_in:

with open(outputFileName, "w") as f_out:

# iterate over each line in input file
for line in f_in:

#encrypt/decrypt the line
lineNew = cipher_cipher_using_lookup(line, key, decrypt=decrypt, shift_type=shift_type)

#write the new line to output file
f_out.write(lineNew)

print("The file {} has been translated successfully and saved to {}".format(fileName, outputFileName))

The function accepts the input file name, output file name, and, the encryption/decryption parameters we saw in the last section.

Let’s encrypt a file ‘milky_way.txt‘ (has the introductory paragraph of the ‘Milky Way’ page on Wikipedia).
We will output the encrypted file to ‘milky_way_encrypted.txt

Let’s encrypt it using the function we defined above:

inputFile = "./milky_way.txt"

outputFile = "./milky_way_encrypted.txt"

fileCipher(inputFile, outputFile, key=3, shift_type="right", decrypt = False)

Output:

Let’s check how our encrypted file ‘milky_way_encrypted.txt‘ looks like now:

Tkh Mlonb Wdb lv wkh jdodab wkdw frqwdlqv rxu Srodu Sbvwhp, zlwk wkh qdph ghvfulelqj wkh jdodab'v dsshdudqfh iurp Eduwk: d kdcb edqg ri
oljkw vhhq lq wkh qljkw vnb iruphg iurp vwduv wkdw fdqqrw eh lqglylgxdoob glvwlqjxlvkhg eb wkh qdnhg hbh.
Tkh whup Mlonb Wdb lv d...

So our function correctly encrypts the file.
As an exercise, you can try the decryption functionality by passing the encrypted file path as an input and setting the ‘decrypt’ parameter to True.
See if you’re able to recover the original text.

Make sure you don’t pass the same file path as both input and output, which would lead to undesired results as the program would do read and write operation on the same file simultaneously.

Multiple shifts (Vigenère Cipher)

So far, we’ve used a single shift value (key) to shift all the characters of the strings by the same no. of positions.
We can also try a variant of this, where we will not use 1 key, but a sequence of keys that are used to perform different shifts at different positions in the text.

For instance, let us say we use a sequence of 4 keys: [1,5,2,3] With this method, our 1st character in the text will be shifted by a 1 position, the second character will be shifted by 5 positions,
the 3rd character by 2 positions, the 4th character by 3 positions; and then again the 5th character will be shifted by 1 position, and so on.
This is an improved version of Caesar Cipher and is called the Vigenère Cipher.

Let us implement the Vigenère Cipher.

def vigenere_cipher(text, keys, decrypt=False):

# vigenere cipher for lowercase letters
n = len(keys)

translatedText =""

i = 0 #used to record the count of lowercase characters processed so far

# iterate over each character in the text
for c in text:

#translate only if c is lowercase
if c.islower():

shift = keys[i%n] #decide which key is to be used

if decrypt == True:

# if decryption is to be performed, make the key negative
shift = -shift

# Perform the shift operation

shifted_c = chr((ord(c) - ord('a') + shift)%26 + ord('a'))

translatedText += shifted_c

i += 1

else:

translatedText += c

return translatedText

The function performs both encryption and decryption, depending on the value of the boolean parameter ‘decrypt’.
We are keeping the count of the total lowercase letters encoded/decoded using the variable i, we use this with modulo operator to determine which key from the list to be used next.
Notice that we have made the shift operation very compact, this is equivalent to the multi-step process of converting between Unicode and character values and computation of the shift we had seen earlier.

Let us test this function using another plain text:

text = "we will call the first manned moon mission the Project Apollo"

encrypted_text = vigenere_cipher(text, [1,2,3])

print("Plain text:\n", text)

print("Encrypted text:\n", encrypted_text)

Output:

Here we are performing the encryption using the keys [1,2,3] and as expected the first character ‘w’ has been shifted by 1 position to ‘x’,
the second character ‘e’ has been shifted by 2 positions to ‘g’, the third character ‘w’ is shifted by 3 positions to ‘z’.
This process repeats with subsequent characters.
Go ahead and perform the decryption process with the same keys and see if you can recover the original statement back.

Why Caesar Cipher is weak?

As simple as it is to understand and implement the Caesar Cipher, it makes it easier for anybody to figure out the decryption without a lot of effort.
Caesar Cipher is a substitution cipher technique where each character in the text is replaced by some fixed character.

If someone identifies the regularity and pattern in the occurrence of certain characters in a ciphertext, they would quickly identify that Caesar Cipher has been used to encrypt the text.
Once you’re convinced that Caesar Cipher technique has been used to encrypt a text, then recovering the original text without the possession of the key is a cakewalk.
A simple BruteForce algorithm figures out the original text in a limited amount of time.

BruteForce Attack

Breaking a ciphertext encoded using Caesar Cipher is only about trying out all the possible keys.
This is feasible because there can only be a limited number of keys that can generate a unique ciphertext.

For instance, if the ciphertext has all the lowercase text encoded, all we have to do is run the decryption step with key values 0 to 25.
Even if the user had supplied a key greater than 25, it would produce a ciphertext that is the same as one of those generated using keys between 0 to 25.

Let’s check out a ciphertext that has all its lowercase characters encoded, and see if we can extract a sensible text from it using a BruteForce attack.
The text at our hand is:

"ks gvozz ohhoqy hvsa tfca hvs tfcbh oh bccb cb Tisgrom"

Let’s first define the decrypt function that accepts a ciphertext and a key, and decrypts all its lowercase letters.

def cipher_decrypt_lower(ciphertext, key):

decrypted = ""

for c in ciphertext:

if c.islower():

c_index = ord(c) - ord('a')

c_og_pos = (c_index - key) % 26 + ord('a')

c_og = chr(c_og_pos)

decrypted += c_og

else:

decrypted += c

return decrypted

Now we have our text but we don’t know the key i.e. the shift value. Let’s write a Brute force attack, that tries all the keys from 0 to 25 and displays each of the decrypted strings:

cryptic_text = "ks gvozz ohhoqy hvsa tfca hvs tfcbh oh bccb cb Tisgrom"

for i in range(0,26):

plain_text = cipher_decrypt_lower(cryptic_text, i)

print("For key {}, decrypted text: {}".format(i, plain_text))

Output:

The output lists all the strings that can be generated from decryption.
If you look at it closely, the string with key 14 is a valid English statement and hence is the correct choice.

Now you know how to break a Caesar Cipher encrypted text.
We could use other, stronger variants of Caesar Cipher, like using multiple shifts (Vigenère cipher), but even in those cases, determined attackers can figure out the correct decryption easily.
So the Caesar Cipher algorithm is relatively much weaker than the modern encryption algorithms.

Conclusion

In this tutorial, we learned what Caesar Cipher is, how it is easy to implement it in Python, and how its implementation can be further optimized using what we call ‘lookup tables’.
We wrote a Python function to implement a generic Caesar Cipher encryption/decryption algorithm that takes various user inputs as the parameter without assuming much.

We then looked at how we can encrypt a file using Caesar Cipher, and then how Caesar Cipher can be strengthened using multiple shifts.
Finally, we looked at how vulnerable Caesar Cipher to BruteForce attacks.

R programlama dili Debian 10 Buster’e nasıl yüklenir?

İstatistiksel hesaplama ve grafikler için yazılım ortamı olup aynı zamanda bir programlama dili olan R, GNU Genel Kamu Lisansı ile lisanslanmış, özgür bir yazılımdır. Yeni Zelanda Auckland Üniversitesinden Ross Ihaka ve Robert Gentleman tarafından ortaya çıkarılan R, hâlihazırda R Geliştirme çekirdek ekibi tarafından geliştirilmektedir. S programlama diline benzeyen R, S’in uyarlaması olarak değerlendirilebilir. R, komut satırı arayüzü kullanıyor olsa da değişik grafik kullanıcı arayüzleri de bulunmaktadır. Bu yazıda, R’yi Debian 10’a yükleme konusunu ele alacağız.

Öncelikle aşağıdaki komutları çalıştırarak sistemin güncel olduğundan emin olmalıyız:

apt update
apt upgrade

Şimdi aşağıdaki komutu kullanarak GPG anahtarını eklememiz gerekiyor:

sudo apt-key adv --keyserver keys.gnupg.net --recv-key 'E19F5F87128899B192B1A2C2AD5F960A256A04AF'

Ardından, aşağıdaki komut çalıştırılarak depo eklenmelidir:

sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/debian stretch-cran35/'

Artık R programlama dilini yükleyebiliriz. Bunun için;

sudo apt update
sudo apt install r-base

komutlarını vermeliyiz. Şimdi de yüklediğimiz R sürümünü yazdırarak kurulumu doğrulayalım:

R --version

Şuna benzer bir çıktı almanız gerekiyor:

$ R --version

R version 3.6.4 (2020-03-16) -- "Holding the Windsock"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

Son olarak CRAN’dan R paketlerinin kurulması gerekiyor. Bunun için;

sudo apt install build-essential

komutuyla gerekli araçları yükleyelim. Ardından, R konsolunu root olarak açalım:

sudo -i R

Ve mesela stringr paketini kuralım:

install.packages("stringr")

Kurulum biraz zaman alacaktır, ancak tamamlandığında, aşağıdakini yazarak kütüphaneyi yükleyelim:

library(stringr)

CRAN paketleri sayfasında daha fazla R paketi bulabilir ve

install.packages ()

komutu ile kurabilirsiniz.

May 09, 2020

Linux: Cinnamon Ya da Gnome, Hangisi Sana Göre?

Linux tabanlı sistemlerle ilgili en güzel şey kullanıcıların beğenilerine göre seçeneklerinin çok ve seçme özgürlüklerinin olmasıdır.Kullanıcıların, paket yöneticileri, masaüstü ortamları, uygulamalar ve hatta önyükleyiciler (sistemin donanımları destekliyorsa) olsun, sistemin hemen hemen her alanında seçim yapmak için birçok seçeneği bulunur.

Bunların en önemlilerinden biri de masaüstü ortamıdır. Masaüstü ortamı, sistemin temel görünümü ve hissi, temel uygulamalar seti ve genellikle donanımınızın yapması gereken iş miktarından oluşur.

GNOME, Ubuntu, Fedora ve daha fazla dağıtımın varsayılan masaüstü iken, Cinnamon Linux Mint’in ‘amiral gemisi’ masaüstü ortamıdır.

Bu yazıda, GNOME ve Cinnamon gibi iki popüler masaüstü ortamını karşılaştırmaya çalışacağız.

Bu yazıda ekran görüntüleri için Cinnamon Remix 20.04 ve Arh Linux GNOME kullanılmıştır.

GNOME

GNOME, başlangıçta GNU Projesi’nin bir parçası olan ancak gerçekten büyüyerek şimdi kendi geliştirme ekibi ve sürecine sahip olan masaüstü ortamıdır. GNOME masaüstü ortamı minimalizme odaklanır. Arayüz temiz, şık ve oldukça akıcıdır. GNOME, 3 numaralı sürüme geçmesiyle birlikte zor zamanlar geçirdi, ancak o zamandan beri, özellikle çok yaygın olarak kullanılan Ubuntu 20.04 Focal Fossa ve Fedora 32’de yer alan en son sürümleri olan GNOME 3.36 ile birlikte çok fazla yeniliğe kavuştu ve oldukça geliştirildi.

CİNNAMON

Cinnamon masaüstü ortamı oyunun tamamında, Gnome’a göre, nispeten daha yeni bir oyuncu. Linux Mint ekibi tarafından geliştirildi ve bu nedenle Linux Mint dağıtımının kendisi ile çok iyi bir uyumluluğa sahip.Cinnamon, GNOME’un 2011 yılında yeni sürüme geçmesiyle birlikte ortaya çıkan çok sert farklılılıkların birdenbire kabullenilememesi nedeniyle başladı ve GNOME 3’ün bir çatalıydı. Daha sonra GNOME depolarından tamamen ayrıldı.Cinnamon, kullanım kolaylığı, işlevsellik ve görsellik sunarak şaşırtıcı bir şekilde Linux Mint’i bugün en popüler Linux dağıtımlarından biri haline getirdi.

Bu kısa girizgahtan sonra, artık karşılaştırmamıza başlayabiliriz!

1. Varsayılan Görünüm ve His

Masaüstü ortamlarının en önemli faktörlerinden birisi  görünümü ve kullanımında yaşattığı hissiyattır.

GNOME

GNOME hakkında herkesin tartışmasız  buluşabileceği ortak nokta, diğer masaüstü ortamlarına kıyasla benzersiz bir görünüme sahip olmasıdır. Sistemi kullanırken bu açıkça göze çarpar. Bu benzersizlik insanlar için ilgi çekici olsa da, bazıları için korkutucu ve ekstra iş anlamına da gelebilir.En basitinden pencereler benzersiz bir kavisli stile sahiptir ve gördüğünüz ayarlar, kullanım kolaylığı için verimli bir şekilde sınıflandırılmıştır.

Ayrıca sol üst köşeye tıklamayla uygulamalar/programlara ulaşılırken, yine sol taraftan ortaya çıkan favorilerin sıralandığı bir rıhtım ve ekranın üst kısmında bulunan panelin ortasından beliren arama alanı gibi ilginç özellikler adeta onun benzersizliğini pekiştirmektedir.

Cinnamon

Sağ köşede zamanı gösteren ve  solda bir uygulama menüsü içeren bir görev çubuğu vardır.Muhteşem ve akıcı bir arayüze sahiptir ve animasyonlar aracılığıyla etkileyici görünmektedir.

Uygulamaların görünümü gayet şık ve üretkenliği hedefledikleri belli oluyor.Aşağıdaki resimde örneğin, ayarlar kategorilerini görebilirsiniz.Minimal ve kullanışlı.Pencere stili oldukça sade ama aynı zamanda modern.

 

Cinnamon kullanım kolaylığına odaklanır, böylece potansiyel kullanıcıların sistemlerine alışmaları daha kolay olur.Şu anda Linux Mint’in bu kadar yaygın kullanılmasının temelinde de bu yatar.

2. Varsayılan Uygulamalar

GNOME

Varsayılan GNOME uygulamaları, her zaman mevcut olan, kendisiyle özdeleşmiş bazı simgeleşmiş uygulamalar içerir.Burada önemli olan, bu uygulamaların GNOME ortamıyla çok iyi entegre edilmiş ve olağanüstü iyi çalışyor olmasıdır.Simgesel uygulamalardan bazıları:

*GNOME’un Gözü: Varsayılan fotoğraf görüntüleyici

*Evince: Belge okuyucu

*Nautilus: Dosya yöneticisi

*Yazılım: GNOME Software store

*Haritalar: Harita okuma uygulaması

*Gedit: Bir metin editörü

*Kişiler, Saat ve Takvim

Bu uygulamaların yanı sıra, neredeyse her dağıtımda Firefox tarayıcısı ve LibreOffice paketi vardır.Gnome’un Epiphany adlı bir de tarayıcısı var.Çok yaygın olarak tercih edilmiyor olsa da, Gnome ile yüksek entegrasyona sahiptir.

Cinnamon

Cinnamon  da oldukça yeterli bir uygulama paketi ile geliyor. Tüm uygulamalar oldukça iyi entegre edilmiştir, ancak Cinnamon’un varsayılan arayüzü diğer birçok masaüstü ortamından çok ta farklı olmadığından fazla fark edilmez. Bildiğimiz gibi,Cinnamon GNOME 3’ün bir çatalıydı, bu yüzden birçok uygulama yine temel olarak GNOME uygulamalarına dayanıyor.Cinnamon uygulamalarından bazıları:

*Xed: Gedit tabanlı metin editörü

*Xviewer: EOG tabanlı resim görüntüleyici

*Xreader: Atril / Evince tabanlı belge görüntüleyici

*Pix: Resim görüntüleyici

*Nemo: Dosya yöneticisi

Cinnamon ile gelen dağıtımlarının çoğunda tıpkı GNOME’da olduğu gibin LibreOffice paketi ve Firefox bulunur. Cinnamon, daha hızlı ve daha az kaynak kullanan uygulamalar kullandığından daha hafif olmasıyla dikkat çekicidir.

3. Uygulama Başlatıcılar

Uygulama başlatıcısı en çok kullanılan bileşenlerden biridir. Bu nedenle, temel bir fikir vermesi açısından karşılaştıralım.

GNOME

GNOME’un uygulama başlatıcısı oldukça harika. Süper tuşuna bastığınızda, ya da farenizi ekranın sol üst köşesine(panelin en sol köşesi) götürdüğünüzde Etkinlikler adı altında ekranda tüm uygulamaların döşenmiş bir görünümünü elde edersiniz, ya da istediğiniz herhangi bir uygulamayı aramak için uygulamalar düğmesine tıklayabilirsiniz.

Cinnamon

Cinnamon uygulama başlatıcısı, menü tabanlı bir sistemdir. Süper tuşuna bastığınızda veya panelde en sol köşede menü simgesine tıkladığınızda ortaya çıkar.Daha kolay gezinme için kategoriler halinde güzel bir şekilde düzenlenmiştir.

4. Uygulama Desteği

Bu belki çoğu kullanıcı için çok ta önemli bir nokta değilken, bazıları için dikkate değer olabilir.GNOME, Cinnamon’a kıyasla çok daha uzun bir süredir bir çok dağıtım tarafından kabul gördüğü ve kullanıldığı için oldukça istikrarlı bir konuma geldi.Uygulama desteği sorunsuz ve bazı büyük dağıtımlar GNOME’u öncelikli masaüstü olarak belirlemiş drumdalar.Şunu da unutmamak gerekir ki, GNOME’un arkasında oldukça kallavi bir geliştirici ekibi var.

Öte yandan, Cinnamon daha yeni ve oldukça umut verici olsa da, Cinnamon’un ‘resmi’ dağıtımı olan Linux Mint diyebiliriz.Bu nedenle neredeyse sorunsuz bir gelişim izliyor.Bu süreçte dağıtımlar arasında tabiri caizse ‘yayılıyor’. Masaüstü ortamlarının en önemli faktörlerinden birisi de görünümü ve kullanımında yaşattığı hissiyattır. Cinnamon bazı büyük dağıtımlar tarafından bir seçenek olarak sunuluyor.Uygulama desteği konusunda çok sıkıntılar yaşanmasa da, gelecekte daha iyi bir konuma geleceği konusunda şüpheye yer bırakmıyor.

5. Özelleştirme
 
GNOME, amaçladığı basitlikten ödün vermemek uğruna, varsayılan olarak minimum kişiselleştirme seçenekleri sunar.GNOME uzantıları(GNOME extensions) ve İnce Ayar Aracı kullanarak, temalar ve simge paketleri ve  üst panel gibi bazı şeyler için sınırlı ve belirli değişikliklere izin verir.Daha ötesine de geçebilmek mümkün olsa da, bu oldukça çaba sarkfetmeyi gerektirir ki, her kullanıcı bunu göze alamayabilir.
 
 
Cinnamon ise varsayılan olarak çok esnektir. Bu konuda Xfce ile benzer şekilde varsayılan olarak bir sürü özelleştirme seçeneği sunar.Temaları, simge paketlerini, pencere stillerini vb.
 
 
Değiştirme araçları varsayılan olarak sunulur. Panel çok esnektir ve başlat menüsü uygulamalarla yapılandırılabilir. Ayrıca Cinnamon resmi sitesinde eklentiler uzantılar mevcuttur.Sonuç olarak Cinnamon’un, daha iyi özelleştirme seçeneklerine sahip olduğu açıktır.
 

6. Dağıtım Seçenekleri

GNOME’un birçok dağıtım tarafından tercih edilmesi hasebiyle daha fazla desteğinin olduğunu söyleyebiliriz.Bu nedenle daha büyük bir kullanıcı kitlesine sahip. Bu, karşılaşacağınız olası sorunlar için daha kolay yardım alabileceğiniz anlamına gelir.

Cinnamon Linux Mint’in ‘amiral gemisi’ konumundadır demiştik. Aslında bu kötü bir şey değil.Bu, Linux Mint’in ‘amiral gemisi’ dağıtımına daha fazla odaklandığı anlamına geliyor ve eğer Linux Mint’i kullanıyorsanız, bu harika bir şey, çünkü geniş ve aktif bir kullanıcı kitlesine sahip.Bu yüzden, herhangi bir sorunla karşılaşma olasılığınız oldukça düşükken, yardım alma olasılığınız oldukça yüksek.

7. Masaüstüne Ortamına Özgü Özellikler

Bazı özellikler masaüstü ortamına özgüdür, bu yüzden karşılaştırma yapmak çok ta mümkün değildir.

GNOME

1. Arama

GNOME’un başlıca özelliklerinden biri de  arama özelliğidir. Süper tuşuna bastığınızda, ya da sol üst köşeye farenzi götürdüğünüzde Etkinliklere açılır.Arama kutucuğuna yazmaya başladığınızda, GNOME aramaya başlayacaktır. Bu özellik, uygulamalar veya dosyalar olsun, her şeyi araştırdığı için mükemmeldir.Oldukça hızlı, oldukça etkileyici.

2. Kabuk Uzantıları

GNOME, sisteminizdeki uygulamalara bazı ekstra özellikler ve erişilebilirlik seçenekleri ekleyebilen kabuk uzantıları sunar. Bu sayede GNOME’u kendinize göre biraz daha özelleştirilmiş bir hale getirebilirsiniz.Bkz. GNOME Shell Extensions

Cinnamon

1. Uygulamacıklar – Masaüstü Uygulamacıkları

GNOME uzantılarına benzer şekilde, Cinnamon da sisteme küçük uygulama özellikleri eklemek için eklentiler kullanır. Bkz. Applets – Desklets

 

2. Eklentiler

Cinnamon için uzantılar küçük görsel ilaveler ve kullanılabilirlik sağlamaya yarar eklentilerdir.Bu, Cinnamon kullanıcıları için, daha iyi üretkenlik ve kullanılabilirlik adına çeşitli seçenekler ekler.Bkz. Extensions

Sonuç olarak, hiçbir masaüstü ortamının bir diğerinden daha iyi olduğunu net olarak söyleyebilmek mümkün değildir.Hepsi özneldir ve daha iyi olup olmamas büyük ölçüde kullanıcıya bağlıdır. Bu yazı ile amaçlanan sadece bir karşılaştırma yapmaktı. Sizin için hangi masaüstü ortamının daha iyi olduğunu anlamanın en iyi yolu farklı dağıtımları denemektir.

Bir gün batımı…

Yine nar gibi kızıl bir gün batımı.

Artık her gün batımında bir anlam var. Batan her günü kutsamaya başladım. Bir adım daha ilerlemek için doğan her güneşe “Hoşgeldin” demem gerekiyor.

Günlerimiz kısa ve sayılı, zaman çok fazla ama bize ait olan içinde bir damla ki günden güne sünger gibi çekiyoruz içimize, yetmiyor…

Feda edilen uykularımızla kaybediyoruz çoğunu, yediğimiz lokmanın dahi tadını çalıyor uykusuzluk, isteksiz ve hevessiz başlıyoruz her güne… Akşam nasıl oldu fark etmeden yığılıyoruz kanepelere. Elimizde telefon ve kumanda ile atletli atalete tavizzsiz şekilde teslim ediyoruz kendimizi… Saat kaç oldu? Bir, iki ve iki buçuk… Çok geç ve iki saatlik kaçamakla bir günü daha yaktık be, değdi mi?

Oysa doğaya dönüş yok. Doğanın doğrusu var ve doğruya dönüş olmalıydı hedef. Vücut saati belli, sabah körü değil elbet fakat en geç kuşluk… Apartmanların çatılarından mesaiye gidiyor ya kuşlar işte tam o vakitir kalkma vakti. Kalk ve kuşlara selam ver ve gün batımından önce geri dönüşlerin kadar her dakika çalış, yorul… Yerdeki ayağını, göğsündeki nefesini ve parmak ucundaki her teması hisset, yeter mi? Yetmez… Suyu kana kana içecek kadar yorul ve ilk lokmanı yutmadan önce önce kokla, iyice çiğne. Sev, sarıl ve gül. Varlığına ve standarta dahi şükret.

Bir sonraki gün batımına boş gelme, bir çayı, bir kahveyi, bir bardak rakıyı veya şarabı ve belki de sadece bir bardak suyu gün batımına karşı içmeyi hak etmiş şekilde çık balkona, yoksa pencerene.

Batıya bakmak şart değil, güneşin batıdan battığını bil yeter, zamandan korkma kuşlar gökte seni beklemez, sen kuşları bekle geçip gittiklerinde iş tamamdır, güneş battı işte…

Sonrası Bir gün batımı… blog.bluzz.net | Günlüğüm ilk ortaya çıktı.

Ubuntu/Debian Sunucular için internet bağlantısı (INTRANET) olmadan, OFFLINE olarak APT/APT-GET kullanarak paket ya da servis kurma işlemleri

Bu işi yapabilmek için en temel olarak elinizde servise ait paketin ve o pakete ait bağımlı paketlerin(dependency) hepsinin olması gerekiyor. Tabi bu bir işlem. İkinci aşama olarak elinizde paketler mevcut ise dpkg komutu ile kurulum sağlayabilirsiniz ama herhangi bir sebepten ötürü apt paket yöneticisine kullanarak kurmanız gerekiyorsa buda mümkün. Bunun için ilk olarak internetli bir...

Continue Reading

May 08, 2020

Vrehi Sti Ftohogitonia

Önceki yazımda anlattığım kullanışlı ve eğlenceli eklentilere buradan devam ediyorum.

Compiz Fusion tarzı bir efekt hatırlamak isteyenlere benim zamanında baya sevdiğim bir sallanan pencereler olayını önereceğim. Compiz alike windows effect isimli eklenti beni Ubuntu Karmic Koala günlerime götürdü.

Ben avatar çok severim, siz de seviyor ve bir köşede görünsün istiyorsanız BigAvatar basit ve tatlı.

Açıkçası iş bilgisayarımda günde 10-50 arası (bazen çok daha fazla) ekran görüntüsü oluşturuyorum. Bir anlatım yapılacağı zaman ekranı yakalama olayı çoğu zaman gerekliliğe dönüşüyor. Ve üzerine bir şeyler de yazılacaksa, görüntüyü print screen ile kaydettim mesela, açtım GIMP üzerine eklemeler.. Tamam zor değil ama daha kolayı da var. Direkt yazabilsem ekrana fena mı olurdu? O zaman Draw On Your Screen yorumlarınıza hazır.

Ben şekilden şekile girsin bilgisayarım, her şey animasyon her şey başka şekil olsun istiyorum diyebilirsiniz. Bana biraz fazla sanırım bu kadarı . Yeni öğrenenlerin heyecanlı ppt sunumları gibi bir görünüm için eklentimizin adı  Animation Tweaks 

Şimdilik bana belki de alıştığım için gerekli gibi gelmiyor, özellikle sol köşeye gitmediğim bi panel iyice kafamı karıştırır sanırım. Ama ihtiyaç duyan varsa burada bulunsun. Paneli aşağı kaydıran bir eklentimiz var, ismi BottomPanel.

Bu da eklentiler için ikinci hatırlatıcı olsun.

δεν έχει ο κόσμος άλλες

Ubuntu..

Debian 10’a TeamViewer nasıl yüklenir?

Son derece başarılı ve kapsamlı bir uzak masaüstü paylaşım programı olan TeamViewer ile internet bağlantısı aracılığı ile TeamViewer ID ve şifresine sahip olduğunuz herhangi bir bilgisayara bağlanabilir ve o bilgisayarı uzaktan kendi bilgisayarınız üzerinden kontrol edebilir ve hatta dosya aktarımı yapabilirsiniz. Dünyada milyonlarca kullanıcı tarafından kullanılan programın Türkçe desteği olması da ayrı bir artısı. TeamViewer’i Android cihazlara kurmak da mümkün. Debian 10’a TeamViewer’ı kurmak için ilk yapmanız gereken şey, GNU/Linux sistemlerde en yoğun biçimde kullandığımız terminali açmaktır tabii.

Ardından, öncelikle depolarımızı güncellememiz gerekiyor.

sudo apt update

Daha sonra, TeamViewer’ın resmi sayfası ziyaret edilerek ve Teamviewer’ın Debian dosyası indirilebilir. Elbette bunu wget komutunu kullanarak terminalden indirmek de mümkündür:

wget https://download.teamviewer.com/download/linux/teamviewer_amd64.deb

Her şekilde, TeamViewer’ı Debian’a kurmak için şu an için şu komutu çalıştırmanız gerekiyor:

sudo apt install ./teamviewer_15.5.3_amd64.deb

Kurulum sonrasında aşağıdaki komutu vererek yazılımı terminalde başlatabilirsiniz:

teamviewer

Elbette ki yazılımı menüden saptayıp açabilirsiniz. Kolay gelsin.

Ubuntu 20.04 LTS, Raspberry Pi Sertifikası Aldı

23 Nisan 2020’de çıkan Ubuntu 20.04 LTS için Canonical, aynı gün onaylanan Raspberry Pi’ların hepsine Ubuntu Server 20.04 için “tam destek” ekledi. Kullanıcılar, Raspberry Pi’lerinde, Canonical’ın düzgün çalışacağını garanti ettiği Ubuntu 20.04’ün yeni özelliklerinin tamamını kullanabilirler. Sertifikalı Olmasının Ne Gibi Avantajları Var? Bir kullanıcı, sertifikalı bir Raspberry Pi

İlledelinux Debian Xfce

İlledelinux Debian Xfce sürümü 1-1-20 kod adıyla 08-05-2020 tarihinde güncellendi. En baştaki 1 rakamı bu çalışmanın ilk sürümü, ikinci 1 rakamı aynı sürümün kaçıncı defa çıkarıldığını, üçüncü 20 rakamı ise çıktığı yıl olduğunu ifade eder. Bu güncellemede bazı küçük hatalar giderildi, ikon tema değişti, Korla ikon tema eklendi, TV ve Radyo özelliğinde değişiklikler yapıldı, bazı özellikler

May 07, 2020

Thunderbird Minimize on Close

E-postalar için Thunderbird Kullanıyoruz.

Oldukça kullanışlı bir ekletiye rastladım.

Eklentinin görevi Thunderbird’i açık tutmak.

Siz yanlışlıkla X ile köşeden kapatsanız bile Thunderbird aktif olarak çalışmaya devam ediyor.

Eklentiyi indirmek için – >> http://troya.tk/39

 

Feeds