diff --git a/001-Jupyter/Create_JupyterKernel_pyenv.ipynb b/001-Jupyter/Create_JupyterKernel_pyenv.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..012a4b76dfcc65a863b44a90c26ff1135c4ae27e --- /dev/null +++ b/001-Jupyter/Create_JupyterKernel_pyenv.ipynb @@ -0,0 +1,510 @@ +{ + "cells": [ + { + "attachments": { + "500ad0ee-8923-43bb-9336-e838a26dc2f1.jpg": { + "image/jpeg": "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wgARCAA/AWMDASIAAhEBAxEB/8QAHAAAAgIDAQEAAAAAAAAAAAAAAAcGCAMEBQEC/8QAGQEAAwEBAQAAAAAAAAAAAAAAAAECAwUE/9oADAMBAAIQAxAAAAG1OLym+/nbqzUsm6vIuTKPn64neBOuGo9AjQOdDKiXRPiTXXPXmCOZSJORKW5agvJk10RdQ/TN6mqto0aZ8q9DS4XdjAScOIq7ZFew10iKZQkxzujLABgAAAAAAAJWqVtaldrhFkK93umu7yuqheZ1q02/py+utxrOhCeN3N1FvBH+vxxu3lRLchT92pJ27Y891JR1+P2Vicacae+FfnDBLKVK3SFo6i1FxKtdzhsuBGJPGOd0ZLAGDGmR/bkWjcR7a630LXlsdIuREY6CrrkV64dMimYUlOZzRyUCaFwxyoi8oMaZRhlInrccsBX+695sBHPHR5PZpy+mbu7YpZQXI8CtjAZ2aLpSw7JGuVbXZJvcd6ic65nm/ngCJtqZa46o2z8m/YxJ4xncnVrS4jUJ6Eg6lpbb0k9cRfaknSVLLC3ga39Y5JCeMzwFnoNsYAZakKmo5rMrrRLLp8uvvthmttgrbGByewL1hfM2tdJqfdwqs7K9BN7jZ+GlNruSH1Ed+Gn8zood9o/QklLGAAqPprAZIxJ+RnfWWTOwgutRmbFyvMk/FShaeXIjIBFgAAAAAAAf/8QALBAAAQQCAQIFBAEFAAAAAAAAAwIEBQYAAQcSExARFTA1FCA0NiEjMTM3QP/aAAgBAQABBQLClQAczykzaKccnzRVVkzxzCffKyQoePj7sxkIat2dtZm/uMXRDvf+ExUAFcbiaxucrcVuam066dY8vw2Ft8ZB6mOY1e5gtBbVc2Ee7ZVyNZRsbZIivTNhnR12NrViFZWOWi5gq5Y96mRY2K8x9eKz5YZFK2cidgRf2q7DvfSmu35tYpHIv5LH8mlgVMhsYmD3T9v673Aim0rxDzS3/tcpyS2kN4cURHkPJR+iLjnB1uj8dzO5WA8LT+t8Sfn8kftw/wDG6/2Pyd+r8U/AZy3+fEuvoqbS4VNqnrVx+0cxnHkZJREeJaRcjElmOx8Y/tORfySvPy7bqXctxOXAodyRkNq2cRuPG7mY1HRn0Ev7XJsMWSh8ZszSDqEi0Q0VnK0v2WOcSG3qQyauEbAOrOvS6zxJ+fyVrptgVaUE39Tkfk79X4p+Azlv88KNk4+4lInUtISAItnDWJhP6kmCpS5q4leJTxl+05F/JYmebqL6oD6M88EJ1z4e6WcGIy51t0KnW30xLEzE0fygI7arE3GtMgJYzWIQsNPtmwfUQdYbA2OXwkOP4WQND1qOgtYQiRItMz69N5xI13t1nI9UcS+i2Geex3H1XNAMuQ6kabQ3t9ijWtBp7vclySEh6zDzc9Atq5bLE+nOVmpzva6Haa9M1mUp8s+m7Bbk0ut7rcUBi51yMT+R8bMnAbNkX8lgzqbFKXYI5DB2aTWIMZLOQvXEgyWCKcLc9Do7b1EuwunSWsS4fJM50wS4arC2nwkWYrAzabQ9KJn9i1pGm93pMijwo8HuCgcdvW7FDV2B6PxEYZ0e5F/JZ6yy07LPMQnG9AVRrDHgxdgYD0abYgG2cjeB9qxzL6DC45ccKTM2qTnfD++6LQ1oL4WxBCGkjnZrbyEhJE9XMOzxEmRzI1wzhkhrPmWcEi+SRT90+sLaWPq0RcitxJwE09dJhXTwhmDozOoPZEkPJN3j2RHXZN6c2RfyWMHrIMKyediUUNTQmv4gZBTxNgERIMZm0dt7czQYmYUfiMvW24jV1QlLi4JXjtOt4QSCp6defZH3dCRonbTrOwPr7acVVwqcdlHcS3EhaQoRmkJ1naRixIJmhp1mhpT4NGe2zrOyjuKahWry1nTry8tea24iaQhI0+z/AP/EACcRAAIBAwMDBQADAAAAAAAAAAECAAMREgQxUSEiQRATIDIzFGFx/9oACAEDAQE/Aa1YURcz+RVqNYGDoIrhr29CwBxmRZrKYj9vU7QEMLiZAnGGtTU2JhdV3hYKQDDuJtAbzIfPWX9yaOndsuJVf20LTSORV/2EheplT90lD9Kkp/SpNP8AksX9nlCmjUu6VrKqYdYzO1VMxaHcRreZa3mdvMBUS4mQMyEyHoyhvsIAFFhNXWD9izRpepfiVEDrZpToYtmTePQu2Sm0WiFTARKBS3fBTs5fmHTeFawjUQQoHiPTzZW4h3EYSwPmWXmAeAZhMIUvMOPQi46SrS1B6XvE0dQ/bpKdNaS4rGGQtMP7mJ5mBGxhRuZgeYEPMwt5gQ8w7iEXmExirj8v/8QAJhEAAgICAQMEAgMAAAAAAAAAAQIAAxESUQQhMRAiM0ETIDJCcf/aAAgBAgEBPwGqo2mCiqsZIhOTmMhXGfQKSNpqFXLCOnu7DzCCpwYVIG0FNjDIECM3iBSwJEHgwDMIImp/fpMfj7Tq3wuvMrTdws6lc1/5ApbsInwPL/jrj/zrl/yGN8SS+x1t9spyzPt2iqi1vqcweDFz9TJPbE93EIYzUzUzUzU+isV8GEljkzpaSnuadU2teOZWxRsrLLthqBiJfhdWGY1xZ9zGvDf1jWZQJxB1P2V7xbiCxP3Es0UrzB4MUzJ4mW4hP2RPyTfmB8Tfn0Bwe8rs6cd8YjdVWPHeWWGw5MU6nM3HE3HELg/UDrxNxxC44m4J8TccQfcBxN5vGbb9v//EAEMQAAIBAwEEBgUJBgQHAAAAAAECAwAEERIFEyExEBQiQVFhMnORobEjMEJSYnFygcEgJDNDs9FTdLLhFSVAY3XC8P/aAAgBAQAGPwKmeRgiLxLMcAUY7CE3rD+YTpT/AHrKGCAeCx5+NWs1+wa4lXWcLpwDy93zE15PndRDJ086utohZI47b+IjDtVLJbo8ZjbSyyfO7Qjc5WGUKnDu0Kf1/wCiaSRgiKMsx7hTRRMY9noexH9f7R6LW0+gzZf8I4msDgOg7Pl09TAEbS/Vk/t+xPdOCyQoXIHPhU8cVvJA0QDdsjjUmyryykukdBrxjGDUtnDaqLWb00JJ1ffTbEstnyxap920mrOW/M5pryWNpVDBdKedNcxRPCFfQVfogjlt5J2lBbsEcMVBcoCqSoHAbzrcPquLnvii+j957qC3FnNbp9cHXSTQuJYnGVZeRr/hXVpte+3O84YzWa6nHbTRNpLBnI7uja/r1/pr0RoyM2tXbh9kZqyuWeR0umVVjwvZ18R7K3yqVGtkwfssR+lQbi2eaebXpiyBgKcEk91QK0EkUrz9XZG+g2nV+YqW10nVHGsmr7yf7fNw2yHT1l8N+Ed3w6braTj0vkY/1/TouLuT0IULVJNKdUkjFmPmaVJG1TWx3TE947j/APeHTtP/AC7/AAraHql+NP6uOl+6j/5Af6hTeuSrj/MH4Do2f6p/iKtrj/Cs9fsWpGvWMkagzS8eLkmmbZdosV4mNKocBx3iri2v4jEgk1RAsDz50Wdgqi/bJJ4DjTfvlvy/xRS+pfo2v69f6a0cc6t99bPbGGKRZXb0SzDHZ8e81suze0kha0ZGlkbGjsjHZPfmuqyWV1q38nbCdjjISDnPnVncm2klCCaORE9JdT5Bx38vfVkZ7dooxd6tAbDrHoOCSDzz4VdtGr7l4YwGeQvxy2eZ+75uOeFdb2raio56Tz6I7e3QyTSHCqKtrNOIiXBPie89Fvs9D2pjvH/COXv+HRfw/RaJX9h/36Ft7uR1kK6uyhPCtosDkG3Y+6toeqX40xPLdRmkI4gijp4/8wH+qm9clXH+YPwHRs/1T/EUFHM2H/pV4ueLQDA/OpLq5fdwRjLNipTYzb3dY1dgrj21dWisEaa7dAzchxonrtvw+waX1L9G1/Xr/TXoA0S7ppN0LjR8mWzjGfv4VPdcd1CXD8PqnB+FSx7i4k3QBd44tQXIzWiGGe6+TWTVAmoYblW6FtdSOEWRhHFnSD4+yoTDrummTeIkC5Onx8qhmTXNviVSONMuSOYx3YoXEhdF3ogYMnaRj4ircTEgzyiFABnial1RTiKJzG8+77AP31cuM6bdir8PAZqH92unWbTu2SLg2RmppJhLHuYlmdSnEKSR+lWyhtXWMmMjkeGaQASiKRtEc7JiNz5HpMrWxhc8TuW0g/lR6nbBHPOQ8WP59DO5CqoySe6ri6H8LOmP8I5dG0LnHZCLH789EV9ZoZZol0PEObL5UNksJXTGjSITvCPA1LNdDTdXGMp9RRyqK8s113MK6Wj73XypbEa10DQu8g7a0Nq7QjeIJlo1k9J2P0jTrHG0jb1DhBmmgs45EjZtZBt88fZVnBcqxt3fD5ttPDHjWz2jhkkXduMohPeKsI5EwerqGVh5V1zZ4kaANmOaMatI+qwpLMxvKuc7uGLSCfOt3IQ1zKdcpHIeVa+ry6OvFtWg4xmm+6g0lvLGoifJZCOja/r1/pr0Ktpv4p2n7ezpE1JxbtEHHAfSznFbS2a0cnW5pJd0gQnWHYkHPLv91bREV11WM7sE7rJPY7iaki63c2UKW0KR7tc6gNX2TW0J7Ccwk20RTMYIkPb8at7jRLHZS2aRq7KSVYMSQ3n2qstoPavb23yyt2eK6iMOw7s499STbpza3V9HgMpGUEektjwqFp4n12c0NsOHpHeDU/3YC++r+N7gw2kl1LqiEXaYavredbWtZElM1w7PCFjJ3mpQOH51sSIrlopow2O7EZraumNjm1hAwOfyjVa26KeqMZpI3HKLKcV9vEVsu1TerPDuYZrU2+oDBALE45eB/ZLMQqjiSe6m2ds982/82YfT8h5dMUci6biX5WTyJ7vZ0B7meO3QnGqVgoreW80c8fLXG2ofsB43WRDyZTkfO7X9ev8ATXo6t1hN9nTjz8M8s+VPC0/yiHSwCscH2VMElVjCdMgH0TjNJruMawGU6W455VHqnxvF1r2W5cvCoXa4XTMMxlctqH5UJYm1IeRxj5vrEGz+vW4Hb0SYZPyxxFfIbOjQ+LyFv7Vpurg7r/CTsp7OmPaW0o9JXtQ27c/xN/bp2OsQiaQ3fATDs/w351s62nuYtlxSiQzT22FXUOQGrl/tWwEN01r1iCWWbQgy+kpjnyzn31uXvC8bT7pY4ypA7PJk9IeOrlUe92l+8PNMj7P0Z0hc4815Dieea2Hi5d4Lt5o2gIGlcamGPZWzLZroG5a+mjmi4atI14BHsqC6N67q+02tDAQNGjJ99Nbi7dTFfAaN6iJuhg40+kTRgkvDIjzMixxlSAMcmX0lP2uVXr2+02uoYUcR28joWlccyABnSOVTM9zvc2ZmcGRWMcnkAOyOfA+FbPjmvpZhf7P3zEhew/Z4rw+1UXVb9us9ZSIlsNusyYxioIbi9O4NnId5Nga5AR78VsKPr0sJuLFpZXjC5ZsL5edbIknumnF/bPI6FQFUjGNPt6Nr+vX+mvQLS6xJcCUq9r/ML6/D35raAO0ra3j63xgkA1Hsr36v0ram0YgTondJ0Xm0ekcfvXn7a2B+O2+FObIRNKLLOmXPHtmtkyQ7Qit95DO5lnQYyWUkYyMcfhSMJkuOH8SP0T840m6NrOf5kHDP3jlXyO0kK/8Aci4/Gv3jaQ0+EUX9zQkhg3k4/nTdpvy8P2BkZxWl1Dr4MM0DjiK3mhd5y1Y40X0jWebY40OyOHLhyrXoXX9bHGvRHPPLvrWZ5dzv+s7ns415zzxnn51vNC7zlqxxrUsaK3iFptKKNXFsDnQwo4cBR7C8Tk8KGpQ2OIyKGFHDgOFDCgY5cOXReylgRPIHA8OyB+nRvNC7zlqxxrU0SM3iVrlQGOArPfWGjVh5itKKFHgPmv/EACgQAQABAwIFBQEBAQEAAAAAAAERACExQVEQYXGBkSAwobHw0cFA4f/aAAgBAQABPyGhC9ZA3WmcFD4Xr4FIPypSasZaWLgR2exhlvEq8Ad0q1c8CG0QwzNEkkMSSSNvdKSLiEJvW6/4lWHZgC6tbACpZ+Q068I3LLzT/JI70IgAQBpwtXJGWvL3A7ZoZOOb3HYEwU1CZMAsaVew2wejdmi7It6ZqWahwqUFIJZEFFAhsCq50voLIsgM268AkTogEGvWsk8eAEw1YByYXRNbozSkkxDB1LPigfyakKjcpp2ztMTMSUaPATUlbeATofRPWYnrLX3mnI+ANxQ0Cd65/CTKNGZbYV6b7DHkqdKUdIrLEBZNyo4KJYQsfPz7a15amoy9zxZoF2C78w7PB4bhHWMHdgqTQDapLT+peJYJ8VuL9DdX7u+v1Nq+F+uBT93f0T+VrBgi63KJdNSLEF2l+KeL6uUXJYmLjQb0YCtqwST3pSn0ME8tGZNLw9a/E5cZ+hSNpxNJ8m8IKc2GptGtXukZk+RkjoZo6dgVhtQQKtzB2lD5Wcl7KXnSbIGxCWFqG9GS5kUYUs4fL20/smSihHSB88AGj1h/m7TJAIev3FeGhK3X+rgS++QQ8Aw3RFJRKnRqC0s7lf3d9NaiA8r/AMpEoFHe1fHNyE/Vfu7+ifyIGUwUQ4GNyL/soJd4Bi8YLt2kIFCd0xgbNAvmCUXmsAdNP6nL0Tz0MxPQj5EROtCTprZy0J1VAiWVCgYvjYovXMlpzJmGnOa8jYLs3WKINMAvrZaF4vF7UOZlMl3OoMzEa1K9eQSiNLIztepPpqjinY51fo6lMwyNJ1inu61wKN7NJrUxEjhfMT4qdyr0aLbyrU4OoOQL89KmnrLsfNvDh0nirw7uz4eKjw2EptpXjlwQix6AGVpZ1KG6WvLPfhJRCHmpfRwQwrV5I7kvbnUOQnELDRMVMbqlm4g82Ve1TV4LzJ1DNtZpm8wCWAFNOY0kwLD0oyBLnLRktOricwUwHqPEGXkKxh1IJL2WoUaYBHkFMetNncJSR7p2T/wbNJnJSQML/rFbr4ZIgO8GvWpwHmyDMxERRRBKr6oeEw6Y1TjPahF5PGcl0oHQvFM5wZBRwsM72lNJegobUK63hpzWs3irrcLeazQ49ACTZ+pJqz4QvBkkW7KNJY7qbICCdXa0Jp2Si6TAyEzC7FSLiqmBz5rykVeBDJQnHRigMguwIIIkCM4zin2RTyQK9Jp6m+uyEQp9chrjC7Eu4mlTkncspNmwdn0m/eTgG61IqWPy+516ZrLBd2KkvBHkI7AHnhDxhSHaWrvwYOQ0k4wVibASXjPrgKESzJ657I952P2Lprl9qULKQ1KkWHS+IezNLQYMMEzBC80+3QF5ndGF96dcYTARKQdyn9S5Fgxhv7ZgE5M5651DFIjQwzwFAZbZ+QZ7zwBABVsBrTImQGWgfXc8bgktL2BQqiYgwuGQrfNlJEnmSgAwS6UFYw3jdNBJwrhU5Y9CFW4LAk0WNSrCY8tKRJmb73mvjMgYkFuusBLOdzSYQXmr+dEEUmvXs9KDczv0xoAicl3Kwm8aBABLN76ZKudCakFoMvlTbIECRi2ZWZxUsu62Utw2Zh3ogANg2NgLjY8U34LQSFuouqutwuR0CSym7xntFuZRJbRJzmOVeaufY8uehE0iEJyZXZqjDkjWrBOhZ5K0Gl2xAhIqMjB4p55gm02lUk+gxyllIXXn7jtuFUm3yKCtoiHwpEvcB5/wrQ1RIPp2HoRQJSSYa1E5AFTwEEDFyuUjDt2mgSYwAkdaDEGcw+CgGJjLDLvVmMOi7utJ5MVHcGlyj6UCyCJRyNpp006QfNNNF2Anu70qwRsGDYqPsCXd6yL9iYd6scRsYGxWOliGDlwOguC4I7wbMDCs2mmaZpFoKYBN22axhoEYrSiyJi9ABRUDYo0B4GD2v//aAAwDAQACAAMAAAAQupSd8/0X33x43T9Ry388888xu4pxcpAarw/cCWZjX1w34wffHrtqRCtoBlUCXonEwTiCM7Ohm4qmHTgPF5F7Ok+88888/8QAJxEBAAIBAgQGAwEAAAAAAAAAAQARMSFBUaHR8BBhcZHB4SCBsfH/2gAIAQMBAT8QyUXBE6hbggQFuJh4afAanVxLUVBqb3tBUkuVYhhLGDodSVmjKi1XiPBS4jT1Phigtg6CebBHH5HXcVpGdmn9QENpQFgy2ickzA8z5nNv8nIRIpwP5GaM3b9whqg6a5/c3xXG5zvwwKhSmvt3UqlYd9IDQ99s0ruGEzPrNSr8B6BlIKIoJoZ9YnCwnxQAWwovaWT25reJXzv6xaio22h3UDahMkXKh6QUGo534YTVtd99II3V9wKzH1+/ODiaa17Mq7ygFOsMpeelRrdqv66eDIKnjNTUeVHLSK7E7wPgi1uz/OnOBN8Xn1gAOzTpzggC0PcXBBeEGAMK5fuAbe2nR94VQ2fhjqzzPeOnO9zCr4Tsen5f/8QAJxEBAAIABAUEAwEAAAAAAAAAAQARITFBYVFxocHwEJGx0SCB4fH/2gAIAQIBAT8Qr5gGbENiuMuAVcDRzLPRaDAzlKq1w4VrFCMGS44Ckg1GDlLhalxTLOHBYZwjyO5EVEEtm3ETP8luLbmD3H4Tej4huw1TbOsO06D6nTk6uETePeAxZVR/IkjZMdppluHOdJ3IhaLjZ8Hxl2vN59xG08P8mLVRHMm3BMQ9F7YloLYAli5coaa4HZ0VThzlEUGV6QKGWnKHtm3WLVQlAkZMHK0VFCLjpO5GLovzz7iZer+S6nPy5bbRc5w+T3ljTLz4l1wYRUNeXcL1S6/v36ECLOEw1Zvb1xhut6n0BBqx7/fSKlcFafUUV8Y7b9IpVpGnDRXmEXdEuNw5r4a/rSLCdm+257RAB4dyGKeftKjYaVCjdcesAZfl/8QAJRABAQACAgIBBAMBAQAAAAAAAREAITFBUWEQcYGRoSAw8LHx/9oACAEBAAE/EMavkMFyhAPbj1rMqeXH7QPTlGMU1Z4Wr9ZMI/YTT9ip8r/R5rtHABSqAqG94zyVeSCbNEGzdswKnlTwSkRL7o6/seMIYSREBTytfM6+b/fAybBih0ALnkqQq4D2vK6E1s5MAxCBeaP1+4GDfEFAGgDFguB+OfzKfhId2HomESIjwnyUwBSpVIVk3iLY1MWi2InfnC3JHhgACQBpEZGlxg5niIVZsAN6hJlCA/jCyAQN6LDIk9hFDaADbmoJbSgLREP7+OZlFmAWVXp4yUSRgwIKUs1ipAlkhBoCI02jciZ9xGZ9Eh5hfWChq+3wif7rNSg+7D7ADzN5cWpTbAuIUIMoKIiKNzr5BjdP4ABNeQw984Ug46wMApqLulqDhddqhorWorT0mTBbFFGDZg5VIOZKMs6DKGg1aI2tgKmiBNYOaNvo9/1qzlTG7vSV5BO8P3jkOYnTY4b6r4IFAlEsflge3PKVdEL+VzT8FJwp+v61fynZQv8AI8PjR/tef8NVjd4O4FGP1QxH3SIgF2JFnUEuairmSAe4IjSXbmnGBg0jiBGtr3g1GPEXU0HtxAFGBv2z/m+M9fAMsmhDNEavq4e+8UlkM84EAdkNNCZ0ZBu8ACjokbzupZNDtizW9ZPqb7lsKQIoEjHDDtB7dpJLoDK4dj44fgTipQ6bX+vSGl8ChtXEdC6wRBoj2YTxDKp2+AbTQCuEaGiU/aT7/CjhOXRtH1t+/AmCNUBdDP8An9Pissb9oAQ8BXWGkHvQiR/CfEUD6SdgC/lfjAJg1wEImOHmhyv/AAK/Gf7Xnjyq/FiNxfkaxEZeYkdPp+zCQCXCQABRAAFVy22LhFdbr0XjHFNQgNBtNdYiGER4C+M/3fGevgGsMgOlhcNNiEMOAVMCu+gntQZB51gdck8FqpsURwo0eGydHAY+mMgGutTCu+C67xLmhroIaCNqqBRMaTdHYAooLWZEaq8aXtgdslGxQFEcR/MGioHDNrRTzhhKoz7oUKi4OVAuVqhFiTl0hE5w1GeScNPDQmlGaorhoFK3diprznkT5XToDmPeM8BvFY7mgMCkdFGmJTE6TVZNVFK+QXFX3Yyg6PRD18FhIMKqHgAVcQ6B55pHh2Z5fw2g6Pph+Pz+/gvyUWkX2UJ2mmyPFd6MQLTQOBQiuEUhSW4QyxBxpyOGYcIFDY6XQuDDYCUZOK82QY0UEN6whTmohFOgY5IMhtewAJDsCwpvHH6DVodg1qxCNi2CsDog2+u8uamYCitGbjgWogApENmnY4nCldLRDoHZEQdOjkKMnUXUHegJZoxAL6NhKdNXkqNTCowhj9/YDbJirgYHK1i/wxWyCAt1M6+AfDFVON6ogbCK0NsDa7kxk9FtRehqjw6Y6ZARxwCfbFj7G6sGUdoj3twu1yAonEkNGzDUZzxbbSXbqAD5gpeAJxYr42ksHtj2mZCHBEABROEzo1yOV2v/AKnw29jA6FQLsukHhxtLRhJdABGlRXEsdLWGJxwV1s84I7CFiQNoIobBHFn9oYS/l3iF44cvERXahBYzS7hx/BScxphVGgDtx9VTUJfqbn4JywYCQKMAqvgO3KADdqIJ9ZHn4C2BEhWFBYLPTlLV5otWlKUuaMY40ur57yxs9KqUCjER9iYx7/eQ8v5wAeX84g9/vCec094cCB6w0gnY3IXn95TzgB3+8ePgG8ZOBNuFlHEPr7DIEAE1hDIMbnVMaZqhiQ8mr2MAyTqaKyIIgN9YSNXOI0xQhKDjAAv3fFSEF6WY8xwrtFpBseTJMmTIf5yZMmT6/n5QKpYP34ZzsjZN41rkGT5235xFT6d6pRudL+DrnAKp4A7fWHoRoTmhxOU3ZCBgQ+JHguNRNhJZO5grRr5dqBHFuMEnUkFkJQUNIBsSnDh569oGtCEBxTGj40ASqVaTeCJsSkCwkoJUPRDE+vZmaCKQowgGu8H0ZGEcQ2sdREcjkzaJEFYaG9KcUgfcm3UuLaGiTeXrMKCVDNWqwOCQxIoHk4Rko5iwlrlnCxQmoFD5MRqCU/RBLRtXRBMdRglJ0QsBFOFlCqHn9SbJhGpq4sGc08ghQBBW6zr4B8fuY26mSdQNUQ1HEXEE8E5tFSeBtJ3nHBqs0OwOxK2Mb7StDjrHILUR1hRK62e8NDwOe8AFlsDduEs/A5lGEOqnF/rS4xOG4Psil2sF84ypnU49rD9gxIKOXX+IYcF2lfmg+oT7wJ83wSwWEp4Yu/eI0REwpsYiaxRXYsQZQehh+DFAnMnB9LZ6uAL4UC4GKh4XCljCBTRdNLXjy4E2IFAILFUFPpkgCIDg5dfy5xxHhIpI05aPTww/Jwh5qbPVwsxIut50LvEQJS4aYm3tx4HVE4+jRo0eMNSEoavha26N85xGnQNwKafZjCTVALS6NGjR4zkuU4pyQaNGjHjHn0aFbTlVuuk+Fw2ha36Gz1cfMAq7ONpcF3CwBXFfOeIaySOIdTPxNLS2XxgGdK6WqCcrzleFRyu2Br+r/9k=" + } + }, + "cell_type": "markdown", + "metadata": { + "toc-hr-collapsed": false + }, + "source": [ + " \n", + "Author: [Filipe Guimaraes](mailto:f.guimaraes@fz-juelich.de)\n", + "--------------------------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create your own Jupyter pyenv-Kernel\n", + "\n", + "Often the standard kernel do not provide all features you need for your work. This might be that certain modules are not loaded or packages are not installed.\n", + "With your own kernel you can overcome that problem easily and define your own environment, in which you work.\n", + "\n", + "This notebook shows you how you can build your own kernel for a **pyenv environment**.\n", + "\n", + "--------------------------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Building your own Jupyter pyenv-kernel is a four-step process\n", + "\n", + "1. **[Download/Install pyenv](#install)**: To start from scratch, and run the full installation.\n", + "2. **[Create and setup environment](#environment)**: To create an(other) environment in an existing pyenv setup.\n", + "3. **[Create/Edit launch script for the Jupyter kernel](#kernel)**: To setup an environment to be run via Jupyter.\n", + "4. **[Create/Edit Jupyter kernel configuration](#json)**: To attach your user to an existing environment via Jupyter. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If `pyenv` is already installed, start at 2.\n", + "If the environment already exists, start at 3.\n", + "If the kernel launch script was already created (e.g., by some other user in the project), start at 4." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<a id='settings'></a>\n", + "### Settings" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To simplifly the process, it is convenient to define a **PYENV_ROOT** path for the central pyenv installation and put on the PATH. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Important**: It is recommended to use a folder inside the $PROJECT file system, as the **$HOME** quota is low. It is also useful to share installation for different users in a single project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "export PYENV_ROOT=${PROJECT_<projectid>}/.pyenv\n", + "export PATH=\"$PYENV_ROOT/bin:$PATH\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Also the environment name can be set in an environment variable **PYENV_ENV** to simplify the process:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "export PYENV_ENV=my_env" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These lines can be added to `~/.bash_profile` (and then `source ~/.bash_profile`) to automatically set the PATH in case of restarting the shell." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "<a id='install'></a>\n", + "## 1. Download/Install pyenv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Installing and setting up pyenv from scratch is very simple. A simple command is needed to install pyenv in **$PYENV_ROOT**:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "curl https://pyenv.run | bash" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "<a id='environment'></a>\n", + "## 2. Create and setup pyenv environment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following steps describe how to create and setup a new pyenv environment to be used as a jupyter kernel. They can be repeated if multiple environments are required." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 2.1 - Activate pyenv and virtual envs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since it is necessary to activate the environment to install the required modules, the following commands should be added to `~/.bash_profile` to activate pyenv and the virtual environments:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eval \"$(pyenv init --path)\"\n", + "eval \"$(pyenv init -)\"\n", + "eval \"$(pyenv virtualenv-init -)\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And activate the lines" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "source ~/.bash_profile" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 2.2 - Install a python version (e.g. `3.10.1`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyenv install 3.10.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note: This step may take a few minutes to complete the installation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 2.3 - Create a new environment **$PYENV_ENV**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The environment is created using the python version installed above" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyenv virtualenv 3.10.1 $PYENV_ENV" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 2.4 - Activate and setup the environment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jupyter requires the `ipykernel` module and its dependencies. To install them, first activate the environment:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyenv activate $PYENV_ENV" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When the environment is successfully activated, the name of the environment is shown between parenthesis in the command line, e.g. `(my_env)`. (To deactivate the environment, use `pyenv deactivate $PYENV_ENV`.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The python version can be checked using" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(my_env)$ python --version\n", + "Python 3.10.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The list of python modules is still empty" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(my_env)$ pip list\n", + "Package Version\n", + "---------- -------\n", + "pip 21.2.4\n", + "setuptools 58.1.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To create a Jupyter kernel, the `ipykernel` and its dependencies are required. `pip` can be used to install it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pip install ipykernel" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Many modules are installed:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(my_env)$ pip list\n", + "Package Version\n", + "----------------- -------\n", + "backcall 0.2.0\n", + "debugpy 1.5.1\n", + "decorator 5.1.1\n", + "entrypoints 0.3\n", + "ipykernel 6.6.1\n", + "ipython 7.31.0\n", + "jedi 0.18.1\n", + "jupyter-client 7.1.0\n", + "jupyter-core 4.9.1\n", + "matplotlib-inline 0.1.3\n", + "nest-asyncio 1.5.4\n", + "parso 0.8.3\n", + "pexpect 4.8.0\n", + "pickleshare 0.7.5\n", + "pip 21.1.1\n", + "prompt-toolkit 3.0.24\n", + "ptyprocess 0.7.0\n", + "Pygments 2.11.2\n", + "python-dateutil 2.8.2\n", + "pyzmq 22.3.0\n", + "setuptools 56.0.0\n", + "six 1.16.0\n", + "tornado 6.1\n", + "traitlets 5.1.1\n", + "wcwidth 0.2.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "<a id='kernel'></a>\n", + "## 3. Create/Edit launch script for the Jupyter kernel" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following steps describe how to create and configure the launch script of a new Jupyter kernel using a pyenv environment. If the environment was created in the $PROJECT folder, many users of the project can follow these steps to create the kernel. The steps assume the variables described in the **[Settings section](#settings)** are set up. Here, they don't need to be set in `~/.bash_profile` or `~/.bashrc`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<a id='launch'></a>\n", + "* 3.1 - Create kernel script to allow access to the pyenv environment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "echo '#!/bin/bash\n", + "\n", + "module purge\n", + "\n", + "export PYENV_ROOT=$PYENV_ROOT\n", + "export PATH=\"$PYENV_ROOT/bin:$PATH\"\n", + "eval \"$(pyenv init --path)\"\n", + "eval \"$(pyenv init -)\"\n", + "eval \"$(pyenv virtualenv-init -)\"\n", + "\n", + "# Activate your Python virtual environment\n", + "pyenv activate \"${PYENV_ENV}\"\n", + "\n", + "exec python -m ipykernel $@' > ${PYENV_ROOT}/versions/${PYENV_ENV}/kernel.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note: the `export` and `eval` lines are repeated here as they are not required to be in `~/.bash_profile` on these steps." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add executable permission to the script:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "chmod +x ${PYENV_ROOT}/versions/${PYENV_ENV}/kernel.sh" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "## 4. Create/Edit Jupyter kernel configuration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These steps describe how to create a Jupyter kernel configuration file, to be able to access the environment via a Jupyter notebook. To access an existing pyenv environment located in **$PROJECT**, only these steps are necessary. The steps assume the variables described in the **[Settings section](#settings)** are set up." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 4.1 - Create a folder for the kernel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mkdir -p $HOME/.local/share/jupyter/kernels/pyenv_${PYENV_ENV}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* 4.2 - Create and adjust the kernel.json file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "echo '{\n", + " \"argv\": [\n", + " \"'\"${PYENV_ROOT}\"'/versions/'\"${PYENV_ENV}\"'/kernel.sh\",\n", + " \"-f\",\n", + " \"{connection_file}\"\n", + " ],\n", + " \"display_name\": \"pyenv_'\"${PYENV_ENV}\"'\",\n", + " \"language\": \"python\"\n", + "}' > $HOME/.local/share/jupyter/kernels/pyenv_${PYENV_ENV}/kernel.json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Restart of JupyterLab might be necessary to see the kernel in the kernel selection overview." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Bash", + "language": "bash", + "name": "bash" + }, + "language_info": { + "codemirror_mode": "shell", + "file_extension": ".sh", + "mimetype": "text/x-sh", + "name": "bash" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}