9. İçe aktarmalar
Uygulama alıştırmasının 1. sürümünde karşılaşılan hata, [import] komutunun rolünü daha ayrıntılı olarak incelememize neden oluyor.

9.1. [import_01] komut dosyaları
[imported] komut dosyası, çeşitli komut dosyaları (modül olarak da adlandırılır) tarafından içe aktarılacaktır:

# modül içe aktarıldı
# bu komut, modül her içe aktarıldığında yürütülecektir
print("2")
# ithal edilen modüle ait değişken
x=4
Bir modül, içe aktarıldığında çalıştırılır. Dolayısıyla, [imported] modülü içe aktarıldığında:
-
- satır görüntülenecek;
-
- satırdaki x değişkeni değerini alacaktır;
[main_01] komut dosyası şöyledir:
# ithal edilen bir modül yürütülür
import imported
# ithal edilen modüle ait x değişkeninin kullanımı
print(imported.x)
-
- satır: [imported] modülü içe aktarılır. Bu, modülün çalıştırılmasına neden olur:
- 2 değeri görüntülenecektir;
- x değişkeni 4 değeriyle oluşturulur;
-
- satır: içe aktarılan modülün x değişkeni kullanılır;
PyCharm'te bir hata bildirilir:
[1] modülünde, PyCharm, [imported] modülünü tanımadığını belirtir. Teknik açıdan bu, [imported] modülünü içeren klasörün PyCharm'in Python Path'inde bulunmadığı anlamına gelir. Python Yolu, içe aktarılan modüllerin arandığı klasörlerin bütünüdür. Bu sorunu çözmek için, [Sources root] modülünün bulunduğu klasörü (burada [import/01] klasörü) belirtmeniz yeterlidir:


Bu işlemden sonra, [import/01] klasörü Pycharm’ın Python Path’ine eklenir ve hata ortadan kalkar:

- [1]'te, [01] klasörünün rengi değişti;
- [2-3]'te artık hata yok;
Çalıştırma sonuçları şu şekildedir:
Yorumlar
-
- satır, içe aktarılan modülün çalıştırılmasının sonucudur;
-
- satır, içe aktarılan modüldeki x değişkeninin değerini gösterir;
Bu örnekten, içe aktarılan bir modülün (veya komut dosyasının) çalıştırıldığı önemli kavramını öğrenmiş oluruz.
[main_02] komut dosyası şöyledir:
# içe aktarılan modülden x değişkeni içe aktarılır
from imported import x
# görüntüleniyor
print(x)
-
- satırda, [from module import objet1, objet2, …] modülünün farklı bir içe aktarma sözdizimi görülmektedir. Burada [imported.x] değişkeni içe aktarılmaktadır. Bu sözdizimi ile x değişkeni, [main_02] betiğinin bir değişkeni haline gelir. Artık değişkenin önüne [imported] modülünü eklemeye gerek yoktur;
-
- satır: [main_02] komut dosyasındaki x değişkeni görüntülenir;
Çalıştırma sonuçları şöyledir:
[main_03] komut dosyası şöyledir:
# ithal edilen modülden görünen her şey ithal ediliyor
from imported import *
# ithal edilen modüldeki x değişkeni kullanılıyor
print(x)
- satırdaki [import *] ifadesi, içe aktarılan modüldeki tüm görünür nesnelerin (değişkenler, işlevler) içe aktarıldığı anlamına gelir.
Sonuçlar şöyledir:
[main_04] komut dosyası şöyledir:
# ithal edilen modülden x değişkeni içe aktarılır
# ve y olarak yeniden adlandırılır
from imported import x as y
# y değişkeni görüntülenir
print(y)
- satır, içe aktarılan modülden bir nesneyi içe aktarabileceğimizi ve ona bir takma ad verebileceğimizi gösterir. Burada [imported.x] değişkeni, [main_04.y] değişkeni haline gelir. Sonuçlar öncekiyle aynıdır.
9.2. [import_02] komut dosyası

İçe aktarılan [module1.py] modülü şöyledir:
# bir işlev
def f1():
print("f1")
İçe aktarılan modül bir işlev tanımlıyor; bu sık karşılaşılan bir durumdur.
[main_01] komut dosyası şöyledir:
# import
import module1
# f1 işlevi çalıştırılıyor
module1.f1()
-
- satırda modül içe aktarılır. Modül çalıştırılacaktır. Burada hiçbir şey görüntülenmez;
-
- satır: İçe aktarılan modülün [f1] işlevi çalıştırılır;
Çalıştırma sonuçları şöyledir:
Not: PyCharm'in 2. satırın içe aktarılması sırasında hata bildirmesini önlemek için, [module1] dosyasını içeren klasörü [Sources Root]'in PyCharm klasörüne yerleştirmek gerekir:

[1] dosyasında, [Sources Root] dosyasının içine yerleştirilen [02] dosyası maviye dönmüştür. Burada bildirilen hatanın komut dosyalarının düzgün çalışmasını engellemediğine dikkat edilmelidir. Nitekim, [main_0x] komut dosyası çalıştırıldığında, komut dosyasının bulunduğu klasör otomatik olarak Python Path’e eklenir. Böylece [module1] bulunur. Bundan böyle, bir ekran görüntüsünde bir klasör mavi renkte görünüyorsa, bu klasör [Sources Root]'in PyCharm'e eklendiği anlamına gelir.
[main_02] komut dosyası şu şekildedir:
# ithalat
from module1 import f1
# f1 işlevi çalıştırılıyor
f1()
-
- satırda, [module1] modülünden [f1] işlevi çağrılır;
-
- satırda f1 işlevi kullanılır;
Sonuçlar, [main_01] komut dosyasının sonuçlarıyla aynıdır.
9.3. [import_03] komut dosyaları

Not: [03], projenin [Sources Root] dosyalarında yer almaktadır.
Yeni komut dosyaları, kendileriyle aynı klasörde bulunmayan [module2] modülünü içe aktaracaktır.
[module2] komut dosyası şu şekildedir:
# bir işlev
def f2():
print("f2")
Dolayısıyla bu komut dosyası, [f2] adlı bir işlev tanımlamaktadır.
[main_01] komut dosyası şöyledir:
# Class2 modülünün içe aktarılması
import dir1.module2
# f2 çalıştırma
dir1.module2.f2()
-
- satır: [module2] modülünün nasıl bulunacağını belirtmek için özel bir notasyon kullanılır. [dir1.module2], [dir1/module2] yolu olarak okunmalıdır: [module2]'i bulmak için, geçerli komut dosyasının bulunduğu klasör olan [main_01]'ten başlanır, ardından [dir1]'e geçilir ve burada [module2] bulunur. Burada, yolun başlangıç noktasının önemli olan komut dosyasının bulunduğu klasör olduğunu unutmamak gerekir;
-
- satır: [module2] içindeki [f2] işlevini çalıştırmak için;
Sonuçlar şu şekildedir:
- satır, [f2] işlevinin sonucu.
[main_02] komut dosyası şöyledir:
# dir1.module2 modülünün içe aktarılması ve yeniden adlandırılması
import dir1.module2 as module2
# f2 işlevinin çalıştırılması
module2.f2()
- satırda, 4. satırın yazımını basitleştirmek için [dir1.module] modülünün adı değiştirilmiştir.
[main_03] komut dosyası şöyledir:
# dir1.module2 modülünden f2 fonksiyonunun içe aktarılması
from dir1.module2 import f2
# f2 işlevinin çalıştırılması
f2()
Bu sefer, 2. satırda sadece [f2] işlevini içe aktarıyoruz; bu işlev, [main_03] betiğinin bir işlevi haline geliyor (4. satır).
Tüm bu komut dosyaları, hem PyCharm bağlamında hem de bir Python konsolunda aynı şekilde çalışır. Bunun nedeni, her iki durumda da yürütülen komut dosyasının bulunduğu klasörün (burada [03] klasörü) Python Yolu’nun bir parçası olmasıdır. Dolayısıyla, [dir1/module2] klasörü bulunur.
9.4. [import_04] Komut Dosyaları

Burada, [dir1] ve [dir2] klasörleri, PyCharm projesinin [Sources Root] klasörüne yerleştirilmiştir.
İçe aktarılan ilk modül [module3]'tir:
# bir işlev
def f3():
print("f3")
İçe aktarılan ikinci modül [module4]'tir:
from module3 import f3
# bir fonksiyon
def f4():
f3()
print("f4")
-
- satırda, [module3]'ten [f3] işlevi içe aktarılır. Burada, [module3] görünür durumdadır çünkü [dir1] dosyası, [Sources Root] içine yerleştirilmiştir;
- 4-6. satırlar: [module3]'teki [f3] işlevini çağıran [f4] işlevi tanımlanıyor;
Ana komut dosyası [main_01] şu şekildedir:
# module4 modülünü içe aktarıyoruz
from module4 import f4
# f4'ün çalıştırılması
f4()
-
- satırda, [module4] modülü içe aktarılır. Bu modül görünür durumdadır çünkü [dir2] klasörü, PyCharm'in [Sources Root] klasörüne eklenmiştir;
-
- satır: [module4] modülündeki [f4] fonksiyonunun çalıştırılması;
PyCharm içinde [main_01] işlevinin yürütülmesinin sonuçları şunlardır:
Şimdi, bir Python terminali (konsolu) içinde [main_01] komutunu çalıştıralım:

Sonuçlar şu şekildedir:
Ne oldu? Python terminali, Python Path'i ve [Sources Root] ile PyCharm komutlarını tanımıyor. Kendi Python yoluna sahiptir. Bu yol içinde her zaman çalıştırılan betiğin klasörü bulunur; bu örnekte [main_01] betiği. Dolayısıyla [import/04] klasörünü tanır. Çalıştırılan betikte şu satırı bulur:
from module4 import f4
Python yorumlayıcısı, Python Yolu’ndaki klasörlerde [module4] dosyasını arar. Ancak [module4], Python Path'te bulunan [import/04] klasöründe değil, Python Path'te bulunmayan [import/04/dir2] klasöründe yer almaktadır. Hata da buradan kaynaklanmaktadır.
Dolayısıyla, daha önce de karşılaştığımız bir sorunla karşı karşıyayız: PyCharm içinde düzgün bir şekilde çalışan bir komut dosyası, bir Python terminali ortamında çökebilir. Bu, çözmemiz gereken tekrarlayan bir sorundur.
9.5. [import_05] komut dosyaları

Not: [dir1] ve [dir2] klasörleri Python Yolu’na eklenmiştir. Şimdiden şunu belirtelim ki burada bir çakışma var: [module3] ve [module4], PyCharm’in Python Yolu’nda iki farklı konumda bulunacaktır:
- [module3] için [import/04/dir1] ve [import/05/dir1]’te;
- [module4] için [import/04/dir2] ve [import/05/dir2]'te;
Böylece, PyCharm projesindeki [Sources Root]'ten [import/04/dir1] ve [import/04/dir2] çıkarılabilir. Burada [import/05/dir1], [import/04/dir1]’in bir kopyasıdır (aynı durum [dir2] için de geçerlidir) ve bu nedenle herhangi bir sorun yoktur. Ancak yine de şunu belirtelim ki, PyCharm dosyasının içinde bile, çakışmaları önlemek için [Sources Root] dosyasının klasör listesine dikkat etmek gerekir.
[main_01] komut dosyası şu şekilde olur:
import sys
# sys.path dosyasını, içe aktarılacak sınıfları içerecek şekilde değiştiriyoruz
# içe aktarılacak sınıfları içeren klasörler
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
# module4'ü içe aktarıyoruz
from module4 import f4
# f4 komutunu çalıştır
f4()
Python Path sorununu çözmeye çalışıyoruz. Hem PyCharm altında hem de bir Python terminalinde sorunsuzca çalışan bir Python Path istiyoruz. Bunun için bunu kendimiz ayarlayacağız.
- 4-6. satırlar: [., ./dir1, ./dir2] dizinlerini Python yoluna ekliyoruz. Bunun çalışması için, yürütme anında geçerli dizinin [import/05] olması gerekir. Bu, PyCharm içinde geçerli olacaktır, ancak birazdan göreceğimiz gibi bir Python terminalinde her zaman geçerli olmayabilir;
-
- satır: [module4] modülünü içe aktarıyoruz. Az önce yaptığımız işlemlerin ardından, bu modülün [./dir2] klasöründe bulunması gerekir;
PyCharm dosyasında çalıştırıldığında şu sonuçlar elde edilir:
Şimdi, bir Python terminalinde:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>python main_01.py
f3
f4
- satırda, çalıştırma dosyası [import/05]'tir.
Şimdi [import/05] dizin ağacında bir üst düzeye çıkalım:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>cd ..
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_01.py
Traceback (most recent call last):
File "05/main_01.py", line 8, in <module>
from module4 import f4
ModuleNotFoundError: No module named 'module4'
-
- satırda, [main_01] çalıştırıldığında artık [import/05] klasöründe değil, [import] klasöründeyiz. Oysa biz şunu yazmıştık:
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
Bu, Python Path'e [import, import/dir1, import/dir2] klasörlerini ekler, ki bu hiç de istediğimiz şey değildir. Python Path'e var olmayan klasörleri (import/dir1, import/dir2) eklemenin hata vermediğini belirtelim.
İlerleme kaydettik ama bu yeterli değil. Python Yolu’na göreceli yollar değil, mutlak yollar eklemeliyiz.
[main_02] komut dosyası, [main_01] komut dosyasının bir varyantıdır ve [config.json] yapılandırma dosyasını kullanır:
{
"dependencies": [
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir1",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir2"
]
}
[dependencies] anahtarının değeri, Python Path'e eklenecek klasörlerin listesidir. Burada göreceli değil, mutlak yolların kullanıldığına dikkat edilmelidir.
[main_02] betiği, [config.json] dosyasını şu şekilde kullanır:
import codecs
import json
import sys
# yapılandırma dosyası
config_filename="C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/config.json"
# json yapılandırma dosyasının okunması
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# sys.path'in değiştirilmesi
for directory in config['dependencies']:
sys.path.append(directory)
# module4 modülünü içe aktarma
from module4 import f4
# f4'ün çalıştırılması
f4()
-
- satır: yapılandırma dosyasının mutlak adının kullanıldığına dikkat edin;
- 8-9. satırlar: Yapılandırma dosyası okunur. İçeriği kullanılarak bir [config] sözlüğü (9. satır) oluşturulur;
- satır 11-13: [config['dependencies']] dizisinin öğeleri Python Path'e eklenir. [config.json] dosyasına mutlak klasör adları yazıldığından, Python Path'e de mutlak adlar eklenir;
-
- satır: [module4] dosyası içe aktarılır. Artık [dir2] dosyası Python Yolu’nda yer aldığı için bu dosyayı bulabilmemiz gerekir;
Çalıştırma, [main_02] ile aynı sonuçları verir; ancak çalıştırma dizini artık [import/05] olmadığında bile komut dosyası çalışmaya devam eder:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_02.py
f3
f4
- satırda, çalıştırma dizini [import]'tir.
İlerleme kaydettik. Şunu gördük:
- Python yolunu kendimiz oluşturmamız gerektiğini;
- uygulama tarafından içe aktarılan modülleri içeren tüm klasörlerin mutlak adlarını buraya eklememiz gerektiğini;
Ancak, komut dosyalarına mutlak yollar eklemek bir çözüm değildir. Proje başka bir sunucuya taşındığı anda çalışmaz hale gelir. Başka bir çözüm bulmamız gerekiyor.
9.6. [import_06] Komut Dosyaları

Not: [06, dir1, dir2] klasörleri, PyCharm projesindeki [Sources Root] klasörüne yerleştirilmiştir. [dir1, dir2] klasörleri, önceki örneklerdekilerle aynıdır.
[config.json] dosyası şu şekildedir:
{
"rootDir": "C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06",
"relativeDependencies": [
"dir1",
"dir2"
],
"absoluteDependencies": [
]
}
İki tür yol tanıtıyoruz:
- mutlak yollar, 7-8. satırlar;
- göreceli yollar, 3-6. satırlar. Bunlar, 2. satırdaki kök dizine göredir. Böylece proje başka bir konuma taşındığında, yalnızca bu satırın değiştirilmesi gerekir;
[utils.py] komut dosyası, [config.json] dosyasını kullanır ve Python yolunu oluşturur:
# ithalatlar
import codecs
import json
import os
import sys
# uygulama yapılandırması
def config_app(config_filename: str) -> dict:
# config_filename : yapılandırma dosyasının adı
# istisnaların üst katmana iletilmesine izin verilir
# yapılandırma dosyasının işlenmesi
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# sys.path dosyasına bağımlılıkların eklenmesi
rootDir = config['rootDir']
# projenin ilgili bağımlılıkları syspath'e ekleniyor
for directory in config['relativeDependencies']:
# bağımlılık syspath'ın başına eklenir
sys.path.insert(0, f"{rootDir}/{directory}")
# projenin mutlak bağımlılıkları syspath'e eklenir
for directory in config['absoluteDependencies']:
# bağımlılık syspath'ın başına eklenir
sys.path.insert(0, directory)
# yapılandırma sözlüğü oluşturulur
return config
# çalıştırılan komut dosyasının klasörüne dönüştürülür
def get_scriptdir():
return os.path.dirname(os.path.abspath(__file__))
-
- satır: [config_app] işlevi, yapılandırma dosyasının adını parametre olarak alır;
- 12-14. satırlar: Yapılandırma dosyası, [config] sözlüğünü oluşturmak için kullanılır;
-
- satır: [sys.path], Python Path'teki klasörlerin listesidir;
- 17-20. satırlar: Yapılandırma dosyasındaki bağımlılıklar Python Path’e eklenir. Bunlar, 20. satırdaki [sys.path] dizisinin başına eklenir. Nitekim Python bir modülü ararken, [sys.path]’teki klasörleri sırayla tarar. Oysa bu belgede, aynı isimdeki modüller [sys.path] dizininin farklı klasörlerinde yer alacaktır. Uygulamanın bağımlılıklarını [sys.path] tablosunun başına yerleştirerek, aynı isimde modüller içerebilecek [sys.path]'teki diğer klasörlerden önce bunların taranacağından emin oluruz;
- 21-24. satırlar: Yapılandırma dosyasının mutlak bağımlılıkları Python Path'e eklenir;
-
- satır: Uygulamanın yapılandırması geri yüklenir;
- 29-30. satırlar: [get_scriptdir] işlevi, o anda çalıştırılmakta olan komut dosyasının (işlev çağrısının bulunduğu) klasörünün mutlak adını döndürür;
Ana komut dosyası [main] şu şekildedir:
# ithalatlar
import sys
from utils import config_app
def affiche_path(msg: str):
# mesaj
print(f"{msg}------------------------------")
# sys.path
for path in sys.path:
print(path)
# ana -------------
try:
# sys.path yapılandırıldı
affiche_path("avant....")
config = config_app(f"{get_scriptdir()}/config.json")
affiche_path("après....")
# module4 içe aktarılıyor
from module4 import f4
# f4 çalıştırma
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
-
- satır: [config_app] işlevi içe aktarılır. [utils] ve [main] aynı klasörde bulunduğundan, bu [import] her zaman çalışır. Nitekim, ana komut dosyasının bulunduğu klasör otomatik olarak Python yoluna eklenir;
- 7-12. satırlar: [affiche_path] işlevi, Python Yolu’ndaki klasörlerin listesini görüntüler;
-
- satır: Uygulama yapılandırılıyor. [config_app] işlevine yapılandırma dosyasının mutlak adının aktarıldığına dikkat edin. Bu komuttan sonra Python Yolu yeniden oluşturuldu;
-
- satır: [module4] modülü içe aktarılır. Python Path'in yeniden oluşturulması sayesinde bu modül bulunacaktır;
-
- satır: [f4] işlevi çalıştırılır;
PyCharm bağlamında, yürütme sonuçları şunlardır:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
…
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
….
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Process finished with exit code 0
Açıklamalar
- 2-13. satırlar: PyCharm'in Python Yolu. Burada, projenin [Sources Root]'ine eklenen tüm klasörler bulunur;
- 14-29. satırlar: [config_app] işlevi tarafından oluşturulan Python Yolu. Burada, 15-16. satırlarda eklediğimiz iki bağımlılık bulunur;
- 22-27. satırlar: komut dosyasını çalıştıran Python yorumlayıcısının sistem klasörleri;
- 28-29. satırlar: çalıştırma normal şekilde gerçekleşiyor;
Şimdi, şimdiye kadar bir yürütme hatasına neden olan bağlama geçelim:
- bir Python terminaline girelim;
- çalıştırılan betiğin bulunduğu klasörden başka bir klasöre geçelim;
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Bu sefer sorun yok (20-21. satırlar). [sys.path]'in, yürütme PyCharm altında gerçekleştiği zamanki klasörleri içermediğine dikkat edelim.
9.7. [import_07] komut dosyaları
Önceki çözümü iki şekilde iyileştiriyoruz:
- [config.json] yapılandırma dosyasını [config.py] komut dosyasıyla değiştiriyoruz. Aslında, jSON dosyası önemli bir sorun yaratıyor: bu dosyaya yorum eklenemiyor. [config.json] sözlüğü, yorum eklenebilme avantajı sunan bir Python sözlüğüyle değiştirilebilir;
- makinedeki tüm Python projelerinden erişilebilen bir modül kullanıyoruz;
9.7.1. Makine genelinde geçerli bir modülün kurulumu

Yukarıda, PyCharm projesinde [packages/myutils] adlı bir klasör oluşturuyoruz (adların önemi yoktur).
[myutils.py] komut dosyası şu şekildedir:
# ithalatlar
import sys
import os
def set_syspath(absolute_dependencies: list):
# absolute_dependencies : mutlak klasör adlarının listesi
# projenin mutlak bağımlılıkları syspath'e eklenir
for directory in absolute_dependencies:
# klasörün varlığı kontrol edilir
existe = os.path.exists(directory) and os.path.isdir(directory)
if not existe:
# bir istisna oluşturulur
raise BaseException(f"[set_syspath] le dossier du Python Path [{directory}] n'existe pas")
else:
# klasör syspath'ın başına eklenir
sys.path.insert(0, directory)
- 6-18. satırlar: [set_syspath] işlevi, parametre olarak kendisine iletilen klasörlerin listesiyle bir Python Path oluşturur;
- 12-15. satırlar: Python Path’e eklenecek klasörün var olup olmadığı kontrol edilir;
[__init.py__] komut dosyası (adının başında ve sonunda iki alt çizgi bulunur. Bu zorunludur) şu şekildedir:
from .myutils import set_syspath
[myutils] betiğinden [set_syspath] işlevini içe aktarıyoruz. [.myutils] notasyonu, [./myutils] yolunu belirtir; dolayısıyla [myutils] komut dosyası, [__init.py] ile aynı klasörde bulunur. [myutils] notasyonu da kullanılabilirdi. Ancak, makine kapsamında bir [myutils] modülü oluşturacağız. Bu durumda [from myutils import set_syspath] notasyonu belirsiz hale gelecektir. Mevcut klasördeki [myutils] komut dosyasını mı, yoksa makine kapsamındaki [myutils] komut dosyasını mı içe aktaracağız? [.myutils] notasyonu bu belirsizliği ortadan kaldırır.
[setup.py] komut dosyası (burada da ad zorunludur) şu şekildedir:
from setuptools import setup
setup(name='myutils',
version='0.1',
description='Utilitaire fixant le Python Path',
url='#',
author='st',
author_email='st@gmail.com',
license='MIT',
packages=['myutils'],
zip_safe=False)
Bu komut dosyasında, oluşturulacak modül tanımlanmaktadır. Burada modülü yerel olarak oluşturacağız. Ancak aynı süreç, resmi olarak dağıtılan bir modül oluşturmak için de kullanılır (bkz. |pypi|). Burada dikkat edilmesi gereken önemli noktalar şunlardır:
-
- satır: Oluşturulan modülün adı;
-
- satır: modülün sürümü;
-
- satır: modülün açıklaması;
- 7-8. satırlar: modülün yazarı;
Bu modülü makine kapsamında yüklemek için şu adımları izleyin:

Ardından Python terminalinde şu komutu girin: [pip install .]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\packages>pip install .
Processing c:\data\st-2020\dev\python\cours-2020\python3-flask-2020\packages
Using legacy setup.py install for myutils, since package 'wheel' is not installed.
Installing collected packages: myutils
Attempting uninstall: myutils
Found existing installation: myutils 0.1
Uninstalling myutils-0.1:
Successfully uninstalled myutils-0.1
Running setup.py install for myutils ... done
Successfully installed myutils-0.1
Artık, makinedeki herhangi bir betik, [myutils] modülünü proje kodlarında bulunmasa bile içe aktarabilir.
9.7.2. [config.py] betiği

[config.py] komut dosyası, uygulamanın yapılandırılmasını sağlar:
def configure():
import os
# yapılandırma betiğinin klasörünün mutlak yolu
script_dir = os.path.dirname(os.path.abspath(__file__))
# syspath'a eklenecek klasörlerin mutlak yolları
absolute_dependencies = [
# yerel klasörler
f"{script_dir}/dir1",
f"{script_dir}/dir2",
]
# syspath'ın güncellenmesi
from myutils import set_syspath
set_syspath(absolute_dependencies)
# yapılandırma geri döndürülür
return {}
-
- satır: [configure] işlevi, uygulamanın yapılandırılmasını sağlar;
- 7-10. satırlar: daha önce [config.json] içinde bulunan sözlük;
- 9-10. satırlar: bir komut dosyası içinde olduğumuz için, [dir1, dir2] klasörlerinin mutlak adlarını doğrudan alabiliriz;
- 12-14. satırlar: Yapılandırmanın Python yolunu tanımlamak için az önce oluşturduğumuz [myutils] modülünün [set_syspath] işlevini kullanıyoruz;
-
- satır: Uygulamanın yapılandırma sözlüğünü döndürüyoruz. Burada sözlük boştur;
9.7.3. [main.py] komut dosyası
Ana komut dosyası [main] şu şekildedir:
# uygulamayı yapılandırıyoruz
import config
config = config.configure()
# syspath yapılandırıldı - içe aktarmalar yapılabilir
from module4 import f4
# ana sayfa -------------
try:
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
- 2-4. satırlar: [config.py] modülü kullanılarak uygulama yapılandırılır. Bu modüle erişilebilir, çünkü ana komut dosyasıyla aynı klasörde bulunur. Ana komut dosyasının bulunduğu klasör ise her zaman Python Yolu'nun bir parçasıdır;
-
- satıra geldiğimizde, Python Yolu, [module4] modülünün bulunduğu klasörü de içerecek şekilde oluşturulmuştur. Dolayısıyla, 7. satırda bu modülü içe aktarabiliriz;
- 10-15. satırlar: geriye sadece [f4] işlevini çalıştırmak kalır;
PyCharm'te yürütme sonuçları şunlardır:
Bir Python terminalinde ve ana komut dosyasının bulunduğu klasör dışında sonuçlar şu şekildedir:
Artık bir uygulamayı yapılandırmak için her zaman aynı şekilde ilerleyeceğiz:
- ana komut dosyası klasöründe [config.py] komut dosyasının bulunması. Bu komut dosyası, iki amacı olan [configure] işlevini içerir:
- uygulama için Python Yolu'nu oluşturmak. Bunun için [config.py], uygulama tarafından kullanılan modülleri içeren tüm klasörleri bildirir ve bunların mutlak adlarıyla Python Yolu'nu oluşturur;
- uygulamanın yapılandırma sözlüğü olan [config]'i oluşturmak;
Bu şemayı uygulama alıştırmasının ikinci sürümüne uyguluyoruz. Hatırlayacağınız üzere, sürüm 1, PyCharm ortamında çalışıyordu ancak bir Python terminalinde çalışmıyordu. Sorun, Python Yolu'ndan kaynaklanıyordu.