# articles

feed_id: http://sametmax.com/?p=24059
title: Introduction aux extensions Python avec CFFI 16
uri: Introduction-aux-extensions-Python-avec-CFFI
url: http://sametmax.com/introduction-aux-extensions-python-avec-cffi/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de Realitix posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p><strong>Préambule</strong></p>
<p>Vous avez réalisé une analyse de votre code et vous avez un bottleneck ?<br />
Vous souhaitez utiliser une bibliothèque bas niveau (C/C++/Rust) ?</p>
<p>Pas de problème, dans cet article, je vais vous expliquer les différentes solutions et pénétrer en profondeur dans la plus charmante d&#8217;entre elles, son petit nom: CFFI.</p>
<p>Sam&amp;Max me faisant l&#8217;honneur d&#8217;accepter mon article, je vais suivre la guideline du site avec un langage détendu et beaucoup d&#8217;exemples.</p>
<h2>Qu&#8217;est-ce qu&#8217;une extension Python ?</h2>
<p>Guido, pendant l&#8217;acte créateur, n&#8217;a pas oublié une chose importante: les extensions Python !<br />
Une extension Python est un module compilé pouvant être importé dans votre code Python.<br />
Cette fonctionnalité est très puissante: cela vous permet d&#8217;utiliser un langage bas niveau (et toutes ses capacités) pour créer un module Python.<br />
Vous utilisez très probablement des extensions Python dans vos projets sans le savoir.<br />
Par exemple, si vous souhaitez embarquer la bibliothèque de calcul physique <a href=https://github.com/bulletphysics/bullet3>Bullet</a>, vous pouvez le faire au sein d&#8217;une extension Python.</p>
<p>Il y a deux points à différencier:</p>
<ul>
<li>Importer une bibliothèque tierce</li>
<li>Améliorer les performances de son code</li>
</ul>
<p>En y réfléchissant bien, créer un code performant revient à créer une bibliothèque tierce et l&#8217;importer au sein de l&#8217;interpréteur.</p>
<h3>Ça laisse rêveur, alors comment fait-on ?</h3>
<p>Plusieurs solutions:</p>
<ol>
<li>L&#8217;API C de CPython. Y&#8217;en a qu&#8217;ont essayé, ils ont eu des problèmes&#8230;<br />
En utilisant cette méthode, vous aurez accès à tout l&#8217;interpréteur Python et vous pourrez tout faire&#8230; mais à quel prix ?<br />
Je ne vous recommande pas cette approche, je me suis cassé les dents pendant 4 mois dessus avec un succès mitigé.</li>
<li>Cython est une bonne solution mais plus orienté sur l&#8217;optimisation de code.</li>
<li>CFFI: le saint Graal, alléluia!</li>
</ol>
<h2>CFFI: Première mise en bouche</h2>
<p>CFFI va vous permettre de créer des extensions Python mais pas que&#8230;<br />
Tout comme le module <code>ctypes</code>, il va permettre d&#8217;importer une bibliothèque dynamique au runtime.<br />
Si vous ne savez pas ce qu&#8217;est une bibliothèque, c&#8217;est par <a href="https://fr.wikipedia.org/wiki/Biblioth%C3%A8que_logicielle">ici</a>.</p>
<p>CFFI va donc vous permettre:</p>
<ul>
<li>D&#8217;importer une bibliothèque dynamique au runtime comme <code>ctypes</code> mais avec une meilleure API -> Mode ABI -> Pas de compilation</li>
<li>De réaliser une extension Python compilée comme `cython` ou comme avec l&#8217;API C de CPYTHON -> Mode API -> Phase de compilation</li>
</ul>
<p>Par rapport à <code>ctypes</code>, CFFI apporte une API pythonic et légère, l&#8217;API de <code>ctypes</code> étant lourde.<br />
Par rapport à l&#8217;API C de CPython&#8230; Ha non! Je n&#8217;en parle même pas de celle-là!</p>
<h3>J&#8217;ai dit qu&#8217;il y aurait beaucoup d&#8217;exemples, alors c&#8217;est parti !</h3>
<p>D&#8217;abord, on installe le bouzin, il y a une dépendance système avec <code>libffi</code>, sur Ubuntu:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> libffi-dev python3-dev</pre></td></tr></table></div>

<p>Sur Windows, <code>libffi</code> est embarquée dans CPython donc pas de soucis.<br />
Ensuite, on conserve les bonnes habitudes avec le classique:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pip <span style="color: #c20cb9; font-weight: bold;">install</span> cffi</pre></td></tr></table></div>

<p>Je vous conseille d&#8217;utiliser un <code>virtualenv</code> mais ce n&#8217;est pas le sujet!</p>
<h3>Les trois modes</h3>
<p>Il y a trois moyens d&#8217;utiliser CFFI, comprenez bien cela car c&#8217;est la partie tricky:</p>
<ol>
<li>Le mode ABI/Inline</li>
<li>Le mode API/Out-of-line</li>
<li>Le mode ABI/Out-of-line</li>
</ol>
<p>On a déjà évoqué les modes ABI et API, mais je n&#8217;ai pas encore parlé de Inline et Out-of-line.<br />
CFFI utilise une phase de &#8220;compilation&#8221; pour parser les header C. Ce n&#8217;est pas une vraie compilation mais une phase de traitement qui peut être lourde.<br />
Le mode Inline signifie que ce traitement va être effectué à l&#8217;import du module alors que Out-of-line met en cache ce traitement à l&#8217;installation du module.</p>
<p>Evidemment, le mode API/Inline ne peut pas exister puisque le mode API impose une phase de &#8220;vraie&#8221; compilation.</p>
<h4>Le mode ABI/Inline</h4>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># On commence par import le module cffi qui contient la classe de base FFI</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cffi <span style="color: #ff7700;font-weight:bold;">import</span> FFI
&nbsp;
<span style="color: #808080; font-style: italic;"># 1 - On instancie l'object FFI, cet objet est la base de cffi</span>
ffi <span style="color: #66cc66;">=</span> FFI<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 2 - On appelle la méthode cdef.</span>
<span style="color: #808080; font-style: italic;"># Cette méthode attend en paramètre un header C, c'est à dire</span>
<span style="color: #808080; font-style: italic;"># les déclarations des fonctions C qui seront utilisées par la suite.</span>
<span style="color: #808080; font-style: italic;"># CFFI ne connaîtra que ce qui a été déclaré dans le cdef.</span>
<span style="color: #808080; font-style: italic;"># La puissance de CFFI réside dans cette fonction, à partir d'un header C,</span>
<span style="color: #808080; font-style: italic;"># il va automatiquement créer un wrapper léger.</span>
<span style="color: #808080; font-style: italic;"># A noter: le code dans cdef ne doit pas contenir de directive pré-processeur.</span>
<span style="color: #808080; font-style: italic;"># Ici, on déclare la fonction printf appartenant au namespace C</span>
ffi.<span style="color: black;">cdef</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;&quot;
    int printf(const char *format, ...);
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 3 - On charge la bibliothèque dynamique</span>
<span style="color: #808080; font-style: italic;"># dlopen va charger la biliothèque dynamique et la stocker dans la variable nommée cvar.</span>
<span style="color: #808080; font-style: italic;"># L'argument passé est None, cela demande à cffi de charger le namespace C.</span>
<span style="color: #808080; font-style: italic;"># On peut ici spécifier un fichier .so (Linux) ou .dll (Windows).</span>
<span style="color: #808080; font-style: italic;"># Seul ce qui a été déclaré dans cdef sera accessible dans cvar.</span>
cvar <span style="color: #66cc66;">=</span> ffi.<span style="color: black;">dlopen</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><em>Comme vous pouvez le voir dans ce bout de code, CFFI est très simple d&#8217;utilisation, il suffit de copier le header C pour avoir accès aux fonctions de la bibliothèque.<br />
A noter: si les déclarations dans le cdef ne correspondent pas aux déclarations présentes dans la bibliothèque (au niveau ABI), vous obtiendrez une erreur de segmentation.</em></p>
<h4>Le mode API/Out-of-line</h4>
<p>Pour bien comprendre ce mode, nous allons implémenter la fonction factorielle.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Comme pour le mode ABI, FFI est la classe principale</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cffi <span style="color: #ff7700;font-weight:bold;">import</span> FFI
&nbsp;
<span style="color: #808080; font-style: italic;"># Par convention, en mode API, on appelle l'instance ffibuilder car le compilateur va être appelé</span>
ffibuilder <span style="color: #66cc66;">=</span> FFI<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># En mode API, on utilise pas dlopen, mais la fonction set_source.</span>
<span style="color: #808080; font-style: italic;"># Le premier argument est le nom du fichier C à générer, le 2e est le code source.</span>
<span style="color: #808080; font-style: italic;"># Ce code source va être passé au compilateur, il peut donc contenir des directives pré-processeur.</span>
<span style="color: #808080; font-style: italic;"># Dans l'exemple, je passe directement le code source mais en général, on va plutôt ouvrir le fichier avec open().</span>
ffibuilder.<span style="color: black;">set_source</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;_exemple&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;&quot;&quot;
    long factorielle(int n) {
        long r = n;
        while(n &gt; 1) {
            n -= 1;
            r *= n;
        }
        return r;
    }
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Comme pour le mode ABI, on déclare notre fonction avec la méthode cdef.</span>
ffibuilder.<span style="color: black;">cdef</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;&quot;
    long factorielle(int);
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Enfin, on va appeler la méthode compile() qui génère l'extension en 2 étapes:</span>
<span style="color: #808080; font-style: italic;"># 1 - Génération d'un fichier C contenant la magie CFFI et notre code C</span>
<span style="color: #808080; font-style: italic;"># 2 - Compilation de ce fichier C en extension Python</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    ffibuilder.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>verbose<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Après éxécution du script, voici ce que l&#8217;on voit dans le terminal:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">generating ./_exemple.<span style="color: black;">c</span>  -<span style="color: #66cc66;">&gt;</span> Étape <span style="color: #ff4500;">1</span>: Génération du fichier C
the current directory <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #483d8b;">'/home/realitix/test'</span>
running build_ext
building <span style="color: #483d8b;">'_exemple'</span> extension  -<span style="color: #66cc66;">&gt;</span> Étape <span style="color: #ff4500;">2</span>: Génération de l<span style="color: #483d8b;">'extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.6-sXpGnM/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/realitix/venv/py36/include -I/usr/include/python3.6m -c _exemple.c -o ./_exemple.o
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -Wl,-Bsymbolic-functions -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -g -fdebug-prefix-map=/build/python3.6-sXpGnM/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 ./_exemple.o -o ./_exemple.cpython-36m-x86_64-linux-gnu.so</span></pre></td></tr></table></div>

<p>Et vous pouvez trouver l&#8217;extension Python `_exemple.cpython-36m-x86_64-linux-gnu.so`.<br />
Étudions le module généré, dans un interpréteur Python:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> _exemple <span style="color: #ff7700;font-weight:bold;">import</span> ffi<span style="color: #66cc66;">,</span> lib
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>ffi<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'CData'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'CType'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NULL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_DEEPBIND'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_GLOBAL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_LAZY'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_LOCAL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NODELETE'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NOLOAD'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NOW'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__class__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__delattr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__dir__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__doc__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__eq__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__format__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__ge__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__getattribute__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__gt__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__hash__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__init__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__init_subclass__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__le__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__lt__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__ne__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__new__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__reduce__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__reduce_ex__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__repr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__setattr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__sizeof__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__str__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__subclasshook__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'addressof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'alignof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'buffer'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'callback'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'cast'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'def_extern'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dlclose'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dlopen'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'errno'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'error'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'from_buffer'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'from_handle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'gc'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'getctype'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'init_once'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'integer_const'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'list_types'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'memmove'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new_allocator'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new_handle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'offsetof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'sizeof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'string'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'typeof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'unpack'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>lib<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'factorielle'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Les modules générés par CFFI contiennent 2 objets ffi et lib.</p>
<ul>
<li>ffi: Les fonctions de l&#8217;API CFFI ainsi que les typedef et structs</li>
<li>lib: Toutes nos fonctions C, ici, il n&#8217;y a que factorielle</li>
</ul>
<p><strong>Ça vous dit d&#8217;utiliser notre extension avec un petit test de performance ? Allons y !</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">from</span> contextlib <span style="color: #ff7700;font-weight:bold;">import</span> contextmanager
&nbsp;
<span style="color: #808080; font-style: italic;"># On import lib qui contient notre fonction factorielle</span>
<span style="color: #ff7700;font-weight:bold;">from</span> _exemple <span style="color: #ff7700;font-weight:bold;">import</span> lib
&nbsp;
<span style="color: #808080; font-style: italic;"># On créé l'équivalent de notre fonction C en Python</span>
<span style="color: #ff7700;font-weight:bold;">def</span> py_factorielle<span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span>:
    r <span style="color: #66cc66;">=</span> n
    <span style="color: #ff7700;font-weight:bold;">while</span> n <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        n -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
        r *<span style="color: #66cc66;">=</span> n
    <span style="color: #ff7700;font-weight:bold;">return</span> r
&nbsp;
<span style="color: #808080; font-style: italic;"># Un petit contextmanager pour mesurer le temps</span>
<span style="color: #66cc66;">@</span>contextmanager
<span style="color: #ff7700;font-weight:bold;">def</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        debut <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">yield</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        fin <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - debut
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f<span style="color: #483d8b;">'Temps écoulé: {fin}'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># On va réaliser un factorielle 25 un million de fois</span>
    loop <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1000000</span>
    rec <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">25</span>
    <span style="color: #808080; font-style: italic;"># Version Python</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> _ <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>:
            r <span style="color: #66cc66;">=</span> py_factorielle<span style="color: black;">&#40;</span>rec<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Version CFFI</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> _ <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>:
            r <span style="color: #66cc66;">=</span> lib.<span style="color: black;">factorielle</span><span style="color: black;">&#40;</span>rec<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le résultat sur ma machine:</p>
<pre>Temps écoulé: 1.9101519584655762
Temps écoulé: 0.13172173500061035
</pre>
<p>La version CFFI est 14 fois plus rapide, pas mal !<br />
CFFI permet de faire vraiment beaucoup de choses simplement, je ne vous ai montré que la surface afin de vous donner envie d&#8217;aller plus loin.</p>
<h2>Où trouver des ressources</h2>
<ul>
<li>La doc de CFFI est vraiment bien, un bon readthedocs classique: <a href="https://cffi.readthedocs.io">cffi.readthedocs.io</a></li>
<li>Une de mes présentations à PyConAU, la version EuroPython est moins bonne: <a href="https://www.youtube.com/watch?v=P6qvhoQGaSk">ICI</a></li>
<li>Mes projets CFFI:
<ol>
<li>vulkan: Mode ABI <a href="https://github.com/realitix/vulkan">ICI</a></li>
<li>Pour les curieux, la version en utilisant l&#8217;API C de CPython <a href="https://github.com/realitix/cvulkan">ICI</a></li>
<li>vulk-bare: Mode API, un module très simple <a href="https://github.com/realitix/vulk-bare">ICI</a></li>
<li>PyVma: Celui-là est très intéressant, mode API qui étend le module vulkan qui en mode ABI, c&#8217;est un très bon exemple</li>
</ol>
</li>
</ul>
<p>A savoir que CFFI a été créé par Armin Rigo et Maciej Fijalkowski, les deux créateurs de Pypy.<br />
Toutes les extensions créées avec CFFI sont compatibles avec Pypy !</p>
<h2>Conclusion</h2>
<p>J&#8217;espère que cette introduction vous a plu. Si les retours sont bons, je pourrai m&#8217;atteler à un tuto plus conséquent.<br />
Vive Python !</p>
<p>Si vous avez des remarques, n&#8217;hésitez pas à me le faire savoir: @realitix sur Twitter</p>


feed_id: http://sametmax.com/?p=24161
title: Do you rotate ? 2
uri: Do-you-rotate-Recently-updated
url: http://sametmax.com/do-you-rotate/
content:
<p>L&#8217;explosion de la taille des logs a tué plus d&#8217;un serveur. Il est amusant de se dire que c&#8217;est du texte qui peut mettre à genoux un serveur de streaming vidéo avec 32 coeurs, 2To de SSD et 64 Go de RAM. Mais un bon access log non contrôlé sous nginx ou même <a href="https://forum.smartcash.cc/t/smartnode-new-start-required-and-other-issues/3105">le log de debug</a> du wallet de la coin smartcash, ça peut prendre par surprise.</p>
<p>Le module <a href="http://sametmax.com/ecrire-des-logs-en-python/">logging</a> de Python a d&#8217;excellentes options pour gérer la taille des logs, notamment le <code>RotatingFileHandler</code>.</p>
<p>Sous Linux, c&#8217;est logrotate qui fait le boulot pour le système. C&#8217;est performant, ça marche super bien, c&#8217;est hyper simple à utiliser, et c&#8217;est dispo partout.</p>
<p>Bref, en prod, un petit vi sur <code>/etc/logrotate.d/ton_projet</code> et pouf, on peut demander une rotation en 10 lignes:</p>
<pre>/var/www/ton_projet/*.log
{
    size 100K
    daily
    rotate 5
    missingok
    notifempty
}</pre>
<p>Y a rien à activer, un cron lance déjà logrotate tous les jours.</p>
<p>Par contre, si votre process utilise systemd pour démarrer, inutile de logger manuellement. Tout ce qui est sur la sortie standard est automatiquement loggué avec rotation et accessible avec un petit <code>journalctl -u ton_process.service --since today</code>.</p>
<p>Bref, attendez encore un peu avant de rajouter logstash à votre stack.</p>


feed_id: http://sametmax.com/?p=24187
title: 13558 Go de rames 25
uri: 13558-Go-de-rames-Recently-updated
url: http://sametmax.com/13558-go-de-rames/
content:
<p>J&#8217;ai une tache celery qui me génère des données de test. Elle est lancée toutes les 5 minutes pour simuler le crawling d&#8217;un site qui popule une base de données, le tout piloté par l&#8217;ORM django, puis dumpé dans redis.</p>
<p>Jusqu&#8217;ici tout va bien.</p>
<p>Mais après un certain temps, ma machine rame, puis se frise.</p>
<p>Et j&#8217;ai du mal à y croire. J&#8217;ai 8 coeurs, un 32 Go de mémoire vive, un SSD d&#8217;un putain de To. On va pas me la faire à l&#8217;envers, c&#8217;est pas un def tout moisi qui va me faire trembler les genoux. C&#8217;est forcément un de ces cons de wallets que j&#8217;ai laissé ouvert, encore codé par un nantais ça !</p>
<p>Mais après une enquête minutieuse, qui a consisté en subtilement killer tous mes processus un par un avec <code>echo "douceur" | sed s/c/l</code>, le constat est là. </p>
<div id="attachment_24189" style="width: 562px" class="wp-caption aligncenter"><a href="media/e357a381.O88afud.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/O88afud.jpg" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/e357a381.O88afud.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/O88afud.jpg" alt="Eukekaca" width="552" height="459" class="size-full wp-image-24189" /></a><p class="wp-caption-text">Eukekaca.</p></div>
<p>Cette fonction est responsable:</p>
<pre lang="python">
def generate_fake_stats(x=1000):

    cur_stats = {
        s.currency.short_code: s
        for s in CurrencyMarketStatsFactory.build_batch(x)
    }
    
    mn_stats: Dict[str, MNMarketStats] = {
        s.masternode.coin.short_code: s
        for s in MNMarketStatsFactory.build_batch(x)
    }

    stats = []

    for code, mns in mn_stats.items():

        cstats: CurrencyMarketStats = cur_stats.get(code)

        if not cstats:
            continue

        dollar_value = float(cstats.dollar_value),
        collateral = mns.masternode.collateral

        stats = {
            'created': int(mns.created.timestamp()),
            'name': cstats.currency.name,
            'code': code,
            'title': f'{cstats.currency.name} ({code})',
            'marketcap': dollar_value * cstats.supply,
            'dollar_value': dollar_value,
            'change_rate': cstats.change_rate,
            'volume': float(cstats.volume),
            'supply': cstats.supply,
            'roi': mns.roi,
            'mn_worth': collateral * dollar_value,
            'node_count': mns.node_count,
            'required_coins': collateral,
        }

    RedisClient.get_instance().jset('marketstats', stats)
    return stats
</pre>
<p>Il m&#8217;a fallu une bonne heure pour trouver ma connerie. J&#8217;ai changé plein d&#8217;options, mis DEBUG sur False, limité la mémoire de Redis, etc.</p>
<p>Mais non, c&#8217;était mon code. Qui générait au bas mot 847390982*1000*16 octets de données, soit 1,355825571×10¹³ pour mes objets Python. </p>
<div id="attachment_24191" style="width: 560px" class="wp-caption aligncenter"><a href="media/e38508bb.iDr73ez.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/iDr73ez.jpg" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/e38508bb.iDr73ez.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/iDr73ez.jpg" alt="J&#039;ai un nouveau mapping clavier qui permet de n&#039;utiliser qu&#039;un doigt" width="550" height="970" class="size-full wp-image-24191" /></a><p class="wp-caption-text">J&#8217;ai un nouveau mapping clavier qui permet de n&#8217;utiliser qu&#8217;un doigt</p></div>
<p>Il y en a un peu plus madame, je vous le mets quand même ?</p>
<p>Nan parce que 13 To pour une pov liste de dicos, c&#8217;est la boucherie.</p>
<p>Alors, sachant que je vous ai éliminé la recherche des causes parallèles et que vous savez que le bug est de ma (grande et stupide) faute, saurez-vous trouver dans ces lignes le d20 qui tombe sur un 1 à tous les jets ?</p>
<p>Si vous ne trouvez pas, la réponse dans quelques jours.</p>
<div id="attachment_24190" style="width: 510px" class="wp-caption aligncenter"><a href="media/80181193.AOPXWnu.gif" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/AOPXWnu.gif" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/80181193.AOPXWnu.gif" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/AOPXWnu.gif" alt="Explain all the humans !" width="500" height="288" class="size-full wp-image-24190" /></a><p class="wp-caption-text">Explain all the humans !</p></div>
<p><strong>EDIT pour la réponse:</strong></p>
<p>Comme plusieurs personnes l&#8217;ont compris, c&#8217;est la virgule sur:</p>
<pre lang="python">
    dollar_value = float(cstats.dollar_value),
</pre>
<p>Qui est responsable de tout ce malheur.</p>
<p>En effet plus loin on fait:</p>
<pre lang="python">
    'mn_worth': collateral * dollar_value,
</pre>
<p>Ce qui, au lieu de multiplier un entier par un float, multiplie un entier par un tuple. En python, c&#8217;est légal, et ça donne ça:</p>
<pre lang="python">
>>> 10 * (7808979.8989,)
(7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989, 7808979.8989)
</pre>
<p>Si collateral est élevé, ce qui est ici mon cas, ça fait de très gros tuples, et le tout dans une boucle.</p>


feed_id: http://sametmax.com/?p=24323
title: Trier un CSV de 5 Go 15
uri: Trier-un-CSV-de-5-Go-6-Recently-updated
url: http://sametmax.com/trier-un-csv-de-5-go/
content:
<p>Marrant, j&#8217;ai jamais eu autant de RAM, et j&#8217;ai jamais eu autant de problèmes de RAM. On est en train de faire un bon dans inefficacité des programmes, et ça va pas aller en s&#8217;arrangeant entre docker, electron et nos chers navigateurs. Une grosse app Python peut devenir assez velue aussi niveau mémoire, même quand on n&#8217;est pas <a href="http://sametmax.com/13558-go-de-rames/">un boulet</a> comme moi.</p>
<p>Et justement, en relisant <a href="http://neopythonic.blogspot.fr/2008/10/sorting-million-32-bit-integers-in-2mb.html">un célèbre post de Guido</a> sur la réponse à la blague &#8220;comment trier un million d&#8217;entiers avec 2M de Ram&#8221;, j&#8217;ai réalisé 2 choses:</p>
<ul>
<li>Le contenu de l&#8217;article est génial.</li>
<li>Le contenu de l&#8217;article est incompréhensible.</li>
</ul>
<p>Or c&#8217;est un peu ma raison d&#8217;être, si vous voulez, de prendre les trucs cools mais imbitables et les rendre utilisables.</p>
<p>Aujourd&#8217;hui, donc, on va trier un CSV de 5Go en Python. Ça parle plus qu&#8217;un fichier de nombres, et puis ça évite d&#8217;expliquer le module <code>array</code> qui est juste une optimisation.</p>
<p>J&#8217;ai pris mes petites mimines, et j&#8217;ai pondu un CSV qui contient 63Mo de:</p>
<pre>A,01/02/2016,2
A,13/07/2011,1
B,24/01/1996,3
C,30/12/1999,1
D,13/07/2011,3
D,01/02/2016,5
E,24/01/1996,4
F,30/12/1999,1
G,13/07/2011,4
H,01/02/2016,4
I,01/02/2016,5
I,13/07/2011,2
A,01/02/2016,2
A,13/07/2011,1</pre>
<p>En copier/coller.</p>
<p>Puis j&#8217;ai lancé un script pour dupliquer le bébé et jusqu&#8217;à atteindre 5,9 Go de taille:</p>
<pre lang="python">with open('data.csv') as infile:
    with open('data2.csv', 'w') as outfile:
        for x in range(100):
            outfile.write(infile.read())
            infile.seek(0)</pre>
<div id="attachment_24327" style="width: 490px" class="wp-caption aligncenter"><a href="media/83cdb381.V3btCPt.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/V3btCPt.jpg" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/83cdb381.V3btCPt.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/V3btCPt.jpg" alt="Si jamais vous doutiez que je vous aime..." width="480" height="360" class="size-full wp-image-24327" /></a><p class="wp-caption-text">Si jamais vous doutiez que je vous aime&#8230;</p></div>
<p>395366400 lignes. Jusqu&#8217;ici tout va bien.</p>
<p>Maintenant, supposons qu&#8217;on veuille trier sur la date. Si vos souvenirs en Python sont exacts (ou si vous avez lu notre super article sur <a href="http://sametmax.com/ordonner-en-python/">Ordonner en Python</a>), vous savez que la solution naïve est de loader le fichier cash pistache, puis d&#8217;appeler dessus <code>sorted()</code> avec le paramètre <code>key</code>.</p>
<p>D&#8217;abord, il faut choisir le callback à passer à <code>key</code>, c&#8217;est à dire la fonction qui va être exécutée pour chaque ligne pour extraire la date de la ligne et permettre ainsi à <code>sorted()</code> de comparer avec les autres dates.</p>
<pre lang="python">>>> str_date = "A,01/02/2016,2".split(',')[1] # récupère la date uniquement
>>> str_date
'01/02/2016'
>>> ''.join(str_date.split('/')[::-1]) # on inverse la date avoir une valeur ordonnable
'20160201'
</pre>
<p>On en fait une fonction:</p>
<pre lang="python"> 
def extract_date(ligne):
    str_date = ligne.split(',')[1]
    return ''.join(str_date.split('/')[::-1])
</pre>
<p>Ensuite on a juste à ouvrir le fichier, trier les lignes, et sauvegarder tout ça dans l&#8217;autre fichier:</p>
<pre lang="python">with open('data2.csv') as infile:
    with open('sorted_data.csv', 'w') as outfile:
        # on fait le tri
        sorted_lines = sorted(infile, key=extract_date)
        # on ecrit les lignes triées dans le nouveau fichier
        outfile.writelines(sorted_lines)</pre>
<p>Easy money, double poney.</p>
<p>Enfin avec un fichier de quelques Mo. Parce que si vous faites ça dans un fichier de 5,9 Go, votre RAM va vomir comme une pom pom girl anorexique.</p>
<div id="attachment_24325" style="width: 824px" class="wp-caption aligncenter"><a href="media/3abb5bad.cfCXCHK.png" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/cfCXCHK.png" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/3abb5bad.cfCXCHK.png" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/cfCXCHK.png" alt="sorted() sur un disque complet, illustré" width="814" height="390" class="size-full wp-image-24325" /></a><p class="wp-caption-text">sorted() sur un disque complet, illustré</p></div>
<p>Comment résoudre ce problème ?</p>
<p>Et bien en faisant tout pareil, mais avec des petits morceaux !</p>
<pre lang="python">
import heapq

from tempfile import TemporaryFile
from itertools import islice

# On garde notre fonction key
def extract_date(ligne):
    str_date = ligne.split(',')[1]
    return ''.join(str_date.split('/')[::-1])

# Liste de tous les fichiers temporaires avec les lignes triées
sorted_temp_files = []

with open('data2.csv') as infile:
    progress = 0
    while True:
        # On lit seulement 3000000 lignes sur 395366400 à chaque tour de boucle
        lines = list(islice(infile, 3000000))

        if not lines:  # plus de ligne ? On sort
            break

        # On affiche où on en est
        print("{:.2f}%".format(progress))
        progress += (3000000 / 395366400 * 100)

        # On tri les lignes, comme avec sorted() mais sur place. 
        # Ça évite de dupliquer les données en mémoire.
        lines.sort(key=extract_date)

        # On crée un fichier temporaire qui va contenir les 3000000 lignes
        # triées
        f = TemporaryFile(mode="r+")
        f.writelines(lines)

        # On rembobine le fichier pour pouvoir relire le contenu plus tard
        f.seek(0)

        # On balance le fichier dans la liste des fichiers triés
        # L'objet fichier hein. Pas le chemin du fichier. C'est pour ça qu'on
        # a fait .seek(0) avant. On va en avoir besoin plus bas.
        sorted_temp_files.append(f)

    # Toute la magie se fait là.
    # On utilise heapq.merge(), qui prend en paramètre plein de trucs qu'on 
    # vient de trier, et permet de se balader dedans comme si c'était un seul
    # gros truc trié, mais sans tout charger en mémoire.
    # En gros il regarde les premières valeurs de tous les itérables, les compares,
    # puis fait retourne un générateur qui yield tout dans l'ordre 
    with open('sorted_data.csv', 'w') as outfile:
        for ligne in heapq.merge(*sorted_temp_files, key=extract_date):
            outfile.write(ligne)

</pre>
<p>Au lieu de charger les 5 Go en mémoire, on plafonne à 400 Mo. Une raison de plus d&#8217;<a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">apprendre à utiliser les générateurs.</a></p>
<div id="attachment_24326" style="width: 590px" class="wp-caption aligncenter"><a href="media/a25140fd.kPXVXqx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/kPXVXqx.jpg" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/a25140fd.kPXVXqx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/kPXVXqx.jpg" alt="Sametmax, c&#039;est de la bombe" width="580" height="326" class="size-full wp-image-24326" /></a><p class="wp-caption-text">Sametmax, c&#8217;est de la bombe</p></div>
<p>Alors évidemment, c&#8217;est long. Y a genre 40 minutes de traitement. Moins si on utilise pypy et qu&#8217;on accepte de up la conso RAM. On code pas en Rust :)</p>
<p>Si vous avez besoin de perfs et que Python reste votre outil de prédilections, 3 solutions restent à votre disposition:</p>
<p>&#8211; Prétraiter le fichier en lui rajoutant une première colonne qui contient un timestamp. Ca c&#8217;est super rapide à trier.<br />
&#8211; Utiliser un truc de numpy ou pandas comme np.memmap().sort(kind=&#8217;merge&#8217;). C&#8217;est du C, donc ça speed.<br />
&#8211; <a href="https://www.chrisstucchio.com/blog/2013/hadoop_hatred.html">Acheter de la ram et tout trier en mémoire</a> avec la solution 1.</p>
<p>EDIT:</p>
<p>Un lecteur m&#8217;a alpagué sur twitter pour me dire qu&#8217;on peut faire ça plus vite et plus facilement avec sort. Oui, évidement.</p>
<p>L&#8217;exercice est académique, il est simplifié pour vous permettre de comprendre <code>heapq.merge()</code>. En réalité, on aura vraiment besoin de ça que pour un cas complexe. Exemple, vous lisez un flux de log une socket et vous checkez les adresses IP d&#8217;abord pour filtrer celles de la liste noire, puis pour les faire matcher une zone géographique et vous triez tout ça et vous le passez à la suite du pipeline. Et le tout doit marcher sous Linux et Windows Server avec juste la lib standard parce que diab est de mauvais poil.</p>
<p>Évidement que si vous voulez juste trier un CSV vous n&#8217;allez pas coder un script python de 30 lignes.</p>


feed_id: http://sametmax.com/?p=24447
title: Je fais mon coming out 47
uri: Je-fais-mon-coming-out-12-Recently-updated
url: http://sametmax.com/je-fais-mon-coming-out/
content:
<p>J&#8217;utilise <a href="https://code.visualstudio.com/download">VSCode</a></p>
<p>J&#8217;ai vraiment du mal à m&#8217;en remettre, et j&#8217;ai des proches qui utilisent Vim et ne sont pas toujours encore à l&#8217;aise avec l&#8217;idée. J&#8217;ai refusé d&#8217;utiliser Visual Studio à de nombreuses reprises, alors tester son petit frère était déjà un pas osé. Un truc Microsoft. Un truc écrit en Javascript.</p>
<p>Mais bon, j&#8217;aime ça, et il faut pas avoir honte de qui on est.</p>
<p>Le fait que ce soit libre et multiplateforme pour un produit Microsoft est surprenant, néanmoins c&#8217;est le maintien continu de l&#8217;excellent comportement de la team derrière qui est le plus bluffant: respectueux, proche des utilisateurs, sans bullshit&#8230;</p>
<p>Le fait que ce soit facile à installer et utiliser pour un projet javascript est surprenant, néanmoins c&#8217;est l&#8217;excellente performance du produit qui est le plus bluffant: temps démarrage, réactivité du scroll, gestion de gros projets&#8230;</p>
<p>Alors j&#8217;ai continué à le garder sous le coude, en parallèle à Sublime Text.</p>
<p>Et quelque chose de subtil a changé, chaque jour, sublime dont j&#8217;ai pourtant payé la licence, me faisait de moins en moins bander. Je sollicitais de plus en plus VSCode. Jusqu&#8217;à ce que ça devienne mon éditeur par défaut.</p>
<p>Oh, ST et moi on se voit toujours. Pour ouvrir un petit fichier vite fait, taper un article, tester un truc.</p>
<p>En revanche dès que c&#8217;est un projet, j&#8217;ai un éditeur Electron made in Redmond pour ça, et il me rend heureux.</p>
<h2>L&#8217;ergonomie de la bestiole</h2>
<p>Les auteurs de VSCode ont pompé tous les éditeurs les plus populaires, goulûment. Ils ont optimisé le temps de démarrage à mort, et même si on n&#8217;a pas la vitesse d&#8217;un ST ou d&#8217;un Vim, ça reste moult fois plus rapide que la vaste majorité de la concurrence. Pas de splash screen à rallonge et ce moment de doute où on n&#8217;est pas sûr d&#8217;avoir vraiment cliqué sur le bouton. J&#8217;aime bien Jetbrain mais le startup de PyCharm me fout les boules à chaque fois.</p>
<p>Côté apparence, on retrouve des lignes épurées avec peu de boutons, des tabs, la fameuse <a href="https://www.youtube.com/watch?v=BteWRBLDbfo">bird view du code</a> de ST, un <a href="https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette">Head Up Display</a>, une statut-bar très riche et le &#8220;<a href="https://www.youtube.com/watch?v=BpSbKmZkKFQ">go to anywhere</a>&#8221; que tout le monde adore depuis Mate.</p>
<p>La force de VSCode c&#8217;est l&#8217;expérience de son équipe : ils ont bien compris ce que les utilisateurs faisaient le plus souvent, et l&#8217;ont mis à porter de main. Un clic pour faire un split view ou afficher le terminal intégré. Mais pas de fonction &#8220;Imprimer&#8221;. Une barre latérale donne l&#8217;accès à 4 autres modes, un pour la recherche dans tout le projet, un pour git (et rien d&#8217;autre), un pour le debuggeur intégré, et un pour installer des extensions.</p>
<p>Une foule de choses sont configurables, avec une interface qui mélange fichiers de config et aide à la saisie. C&#8217;est étrange la première fois qu&#8217;on met le nez dans &#8220;paramètres de l&#8217;utilisateur&#8221; ou &#8220;ouvrir les raccourcis clavier&#8221;. Ni vraiment une fenêtre avec des formulaires. Ni vraiment un JSON à éditer à la main. Un peu des deux. Et c&#8217;est super bien fait.</p>
<p>Ceci dit, comme les réglages par défaut sont assez sains, un junior n&#8217;aura pas à s&#8217;en soucier et pourra tout de suite commencer à introduire des bugs dans votre projet.</p>
<h2>L&#8217;éditeur</h2>
<p>Aucune innovation. Aucune tentative de faire différent de la concurrence. C&#8217;est du classique, c&#8217;est propre, et ça marche. On peut bien entendu choisir entre plusieurs mode de saisie (mode VI, Emarcs, Sublime, etc), mais perso je reste avec le mode original et quelques raccourcis custo.</p>
<p>Derrière, toutes les fonctionnalités modernes sont là: <a href="https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_multi-cursor-selection">multi-curseur</a>, <a href="https://stackoverflow.com/questions/29953479/multiple-cursors-in-visual-studio-code">sélection</a>/recherche incrémentale, <a href="https://code.visualstudio.com/docs/languages/python#_snippets">snippets</a> (<a href="https://code.visualstudio.com/docs/editor/emmet">emmet</a> inclus !), complétion des mots les plus utilisés, navigation par symbole, <a ref="https://www.infoq.com/news/2016/12/visualstudiocode-18-released">hot exit</a>. L&#8217;avantage, c&#8217;est que comme VSCode joue la carte de l&#8217;interface minimaliste, on n&#8217;a pas besoin de connaitre tout ça, et on peut juste commencer à taper, tout en apprenant chaque feature au fur et à mesure de ses progrès. C&#8217;est un excellent éditeur pour débutant en ce sens. Mais les powers users qui aiment malgré tout la souris et les onglets y trouveront leur compte.</p>
<p>La coloration syntaxique est irréprochable (heureusement), mais on voit qu&#8217;ils ont du faire des concessions. Par exemple au démarrage, seule la partie de votre viewport est colorée. Il faut attendre une à deux secondes sur les gros projets pour que le reste du fichier le soit, histoire de pas freezer tout le bouzin.</p>
<p>Le bon côté de ça c&#8217;est que c&#8217;est très fluide. Bon évidemment j&#8217;ai 8 coeurs et 32Go de RAM. J&#8217;ai tenté l&#8217;aventure sur une VM avec 2 de rames et un tout petit coeur, et c&#8217;est pénible. Au repos avec quelques tabs ouverts, le truc s&#8217;engouffre quand même ses 700Mo de mémoire vive. N&#8217;oubliez pas que c&#8217;est du V8 derrière.</p>
<p>En comparaison ST en bouffe 300, et Vim, heu, LOL.</p>
<h2>Intégration Git</h2>
<p>L&#8217;intelligence de cette feature, c&#8217;est qu&#8217;ils se sont limités aux opérations simples et courantes. Permettre de naviguer dans l&#8217;espace temps ou de lancer son <code>merge --rebase</code>, c&#8217;est dur à faire correctement. Donc VSCode n&#8217;essaye pas.</p>
<p>Il affiche juste la liste des fichiers qui sont modifiés et/ou en staging, permet de les bouger de l&#8217;un à l&#8217;autre ou annuler les modifications, et de faire un commit rapidement. Un clic sur un fichier l&#8217;ouvre en mode diff avec HEAD. C&#8217;est tout.</p>
<p>C&#8217;est pas 1% de ce que permet de faire Git.</p>
<p>Mais c&#8217;est facilement 69% de mon usage de Git. Du coup c&#8217;est super pratique. Combiné avec le terminal intégré, et vous pouvez gérer presque tout le repo sans sortir de l&#8217;éditeur.</p>
<h2>Le debuggeur</h2>
<p>Je ne l&#8217;utilise jamais et je préfère <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">ipdb</a>. Pour le moment, en Python, il est trop lent. Les devs JS en disent du bien, vu qu&#8217;apparemment il est capable de se connecter directement au navigateur et comprend TypeScript de manière transparente.</p>
<h2>La recherche</h2>
<p>Rien à dire. C&#8217;est rapide. Ça marche. Ça supporte les trucs les plus importants: case insensitive (activé par défaut), regex, in sélection, dans tous les fichiers, filtrés par extension, et tout le bordel. Cliquer sur le résultat ouvre le fichier à la bonne ligne. Pas de modale qui bloque l&#8217;UI.</p>
<p>Pas de surprise, donc. Mais pas de mauvaises surprises.</p>
<p>L&#8217;indexage est configurable par projet, ce qui est indispensable dès que vous avez quelque chose d&#8217;un peu complexe.</p>
<p>La recherche de fichiers par nom est absente puisque ferait doublons avec &#8220;Go To Anywhere&#8221;.</p>
<h2>Intégration des langages</h2>
<p>Là, on attaque la partie intéressante. VSCode est neutre dans son traitement des langages, et toutes les features avancées se font donc via des extensions. L&#8217;astuce, c&#8217;est que l&#8217;équipe supporte officiellement certaines extensions, et elles sont donc d&#8217;excellente qualité.</p>
<p>Le support de Python est phénoménal. C&#8217;est simplement le meilleur après celui de PyCharm (et de pas beaucoup), ce qui n&#8217;est pas peu dire, vu que Jetbrain fait probablement des messes noires et des sacrifices à Quetzalcoatl pour obtenir ce résultat.</p>
<p>Python est notoirement difficile à outiller de par son très grand dynamisme.</p>
<p>Mais là, c&#8217;est beau.</p>
<p>Pylint est activé par défaut, et flake8 ainsi que mypy sont optionnellement activables. Leurs préréglages sont de bonne qualité, particulièrement celui de mypy qui est normalement inutilisable out of the box. L&#8217;éditeur vous prompte pour l&#8217;installation quand il détecte qu&#8217;ils sont absents, et lance tout ça pour vous.</p>
<p>Tout est configurable par projet, et donc si vous spécifiez un virtualenv pour votre projet (ce qui vous devriez toujours faire), VSCode va détecter que les outils ne sont pas dedans, vous proposer de les installer, et le faire pour vous.</p>
<p>Du coup, bénéficier des types hints, de la détection des erreurs de syntaxes, des variables non déclarées et des imports manquants ou inutiles est beaucoup plus facile que sur n&#8217;importe quel compétiteur. Ok, sauf PyCharm. Mais personnellement je l&#8217;appelle PyChiderme.</p>
<p>Si VSCode ne supporte pas nativement un outil, il existe probablement une extension pour ça. Par exemple, il y a une extension pour <a href="https://github.com/ambv/black">black</a>, qui est à Python ce que <a href="https://golang.org/cmd/gofmt/">Gofmt</a> est à Go, et que j&#8217;installe donc maintenant à chaque nouveau projet.</p>
<p>L&#8217;intégration de ces outils est excellente :</p>
<ul>
<li>Les linters de Python sont naturellement lents, mais VSCode les lance en asynchrone et ça ne ralentit pas son UI.</li>
<li>L&#8217;affichage des erreurs est claire, mais discret. Ça limite l&#8217;effet sapin de Noël.</li>
<li>à côté du terminal intégré existe une fenêtre qui liste toutes les erreurs par fichier. On peut ainsi parcourir son projet erreur par erreur.</li>
</ul>
<p>VScode m&#8217;a même surpris à détecter mes tests unitaires, m&#8217;a proposé d&#8217;installer <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-3/">pytest</a> puis de lancer tout ça.</p>
<p>Cependant, pour vraiment parler de l&#8217;intégration de Python dans VSCode, il me faut mentionner IntelliSense. C&#8217;est un terme marketing inventé par MS pour caractériser toutes les fonctionnalités autour de la compréhension que l&#8217;éditeur à du code, et des opérations qu&#8217;il propose dessus.</p>
<p>Ok, ok, c&#8217;est un mot 100% bullshit.</p>
<p>Mais bordel, ça marche.</p>
<p>La complétion du code est excellente, et marche sans aucun réglage. Avec la lib standard bien entendu, mais aussi avec votre code, et toutes les libs installées dans votre virtualenv (si vous avez précisé le chemin vers ledit env dans les settings du projet, of course, il est pas devin).</p>
<p>VSCode affiche les docstrings, les params et propose d&#8217;aller à la définition de n&#8217;importe quoi en un clic.</p>
<p>Et si comme moi vous avez passé un temps fou à essayer d&#8217;obtenir le même résultat sous ST/Vim/Whatever en chargeant what mille plugins et en changeant 600 valeurs de configs, vous comprendrez que c&#8217;est juste, topissime.</p>
<h2>Quelques infos</h2>
<p>Les réglages de VSCode de base sont bons. C&#8217;est vraiment une partie de ce qui fait la force du projet: moins de bordel à faire soi-même. Mais comme il est bien configurable, il ne faut pas s&#8217;en priver. Quelques trucs que je fais toujours:</p>
<h3>Installer une police avec des ligatures</h3>
<p>Genre <a href="https://github.com/tonsky/FiraCode">Fira-Code</a>.</p>
<p>Et activer les settings:</p>
<pre lang="javascript">
    "editor.fontFamily": "'Fira Code', 'Droid Sans Mono', 'Courier New', monospace, 'Droid Sans Fallback'",
    "editor.fontLigatures": true,</pre>
<h3>Exclure plein de fichiers</h3>
<p>J&#8217;ai pas du tout envie que &#8220;Go to anywhere&#8221;, la recherche des fichiers ou l&#8217;indexage git charge des trucs inutiles. Donc j&#8217;ai des settings de base de nazi:</p>
<pre lang="javascript">    "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/.DS_Store": true,
        "**/dist": true,
        "**/build": true,
        "**/env/**": true,
        "**/venv/**": true,
        "**/virtualenv/**": true,
        "**/node_modules": true,
        "**/bower_components": true,
        "**/vendors": true,
        "**/__pycache__": true,
        "**/**/*.pyc": true
    },
    "files.watcherExclude": {
        "**/.git/objects/**": true,
        "**/node_modules/**": true,
        "**/build/**": true,
        "**/dist/**": true,
        "**/env/**": true,
        "**/venv/**": true,
        "**/virtualenv/**": true,
        "**/bower_components/**": true,
        "**/vendors/**": true,
        "**/__pycache__": true,
        "**/**/*.pyc": true
    },</pre>
<p>Mes settings par projet sont généralement encore plus restrictifs.</p>
<h3>Je change les params de zoom</h3>
<pre lang="javascript"> "window.zoomLevel": 2,
 "editor.mouseWheelZoom": true,
 "editor.fontSize": 10,</pre>
<h3>Je vire la télémétrie</h3>
<p>Je suis pas sous Windows 10, merde.</p>
<pre lang="javascript">    "telemetry.enableCrashReporter": false,
    "telemetry.enableTelemetry": false,</pre>
<h3>Je mets des barres verticales</h3>
<pre lang="javascript">    "editor.rulers": [
        79, # PEP8
        88, # Black
        120 # Javascript
    ],</pre>
<h3>Ergonomie perso</h3>
<pre lang="javascript">
    "editor.renderWhitespace": "none", # overridé par projet
    "editor.renderIndentGuides": true,
    "editor.minimap.enabled": true,
    "editor.minimap.renderCharacters": true,
    "editor.autoIndent": true,
    "window.restoreWindows": "all",
    "window.openFoldersInNewWindow": "on",
    "editor.acceptSuggestionOnEnter": "off",
    "editor.tabCompletion": true,
    "emmet.triggerExpansionOnTab": true,
</pre>
<h3>Pour un Python heureux</h3>
<pre lang="javascript">    "python.venvPath": "~/.local/share/virtualenvs/",
    "python.linting.mypyEnabled": true,
    "python.linting.enabled": true,
    "python.pythonPath": "/usr/bin/python3.6", # je l'override dans les settings de projet
    "black.path": "/home/user/.local/bin/black", # black a besoin de Python 3.6
    "python.formatting.provider": "none", # pour black
    "editor.formatOnPaste": true,
    "files.associations": {
        ".pylintrc": "ini"
    },
    "python.linting.flake8Enabled": true,
    "python.unitTest.pyTestEnabled": true,
    "python.linting.pylintEnabled": true,
</pre>
<h3>J&#8217;installe généralement ces extensions</h3>
<ul>
<li><strong>Python</strong>. Logique.</li>
<li><strong>Color highlight</strong> pour que les code hexa soient surlignés avec la couleur qu&#8217;ils représentent.</li>
<li><strong>Black</strong>, parce que je ne veux plus jamais reformater du code manuellement de ma vie.</li>
<li><strong>Django template</strong> et <strong>jinja</strong>, pour un meilleur support des templates django et jinja en coloration syntaxique.</li>
<li><strong>Editor config</strong> parce que j&#8217;ai toujours un .editorconfig à la racine de mes projets.</li>
<li><strong>gitignore</strong>, <strong>systemd-init-file</strong>, <strong>restructured text</strong> afin d&#8217;avoir la coloration syntaxique pour eux aussi</li>
<li><strong>path intellisense</strong>, comme ça j&#8217;ai la complétion sur les chemins de fichier.</li>
<li><strong>Rainbow CSV</strong>, qui affiche chaque colonne d&#8217;un CSV dans une couleur différente.</li>
<li><strong>git history</strong> pour afficher l&#8217;historique d&#8217;un fichier ou d&#8217;une ligne.</li>
</ul>
<h3>Astuces utiles</h3>
<p>VSCode vient avec les raccourcis traditionnels des éditeurs graphiques: <kdb>ctrl</kdb> + <kdb>F</kdb> pour rechercher, <kdb>ctrl</kdb> + <kdb>shift</kdb> + <kdb>f</kdb> pour rechercher dans le projet, <kdb>ctrl</kdb> + <kdb>d</kdb> pour la sélection incrémentale, <kdb>ctrl</kdb> + <kdb>p</kdb> pour le &#8220;go to anywhere&#8221;, <kdb>ctrl</kdb> + <kdb>shift</kdb> + <kdb>p</kdb> pour le head up display, <kdb>ctrl</kdb> + <kdb>s</kdb> pour sauvegarder, <kdb>ctrl</kdb> (+<kdb>shift</kdb>) pour se balader (sélectioner) de mot en mot, etc.</p>
<p>Il possède aussi quelques trucs sympas dont on parle moins dans les tutos:</p>
<ul>
<li>clic milieu active la sélection verticale</li>
<li>Dans un shell, <code>code -r</code> ouvre un fichier dans la fenêtre en court, et <code>code -n</code> dans une nouvelle fenêtre. <code>code --diff foo bar</code> ouvre les deux fichiers en mode comparaison.</li>
<li>Dans un projet, le fichier <code>.vscode/tasks.json</code> contient la configuration des taches à lancer. Compilation, tests unitaires, debuggage, serveur&#8230; On peut lui faire faire n&#8217;importe quoi.</li>
<li>&#8220;Join line&#8221; n&#8217;a aucun shortcut par défaut. C&#8217;est une opération courante, donc je vous conseille de la mapper. Perso je la mets sur <kdb>ctrl</kdb> + <kdb>j</kdb>.</li>
<li><kdb>Ctrl</kdb>+<kdb>Shift</kdb>+ <kdb>O</kdb> permet de se déplacer vers n&#8217;importe quel symbole. C&#8217;est pratique, mais personne ne s&#8217;en souvient jamais. Plus facile à retenir: faire un &#8220;go to anywhere&#8221; (<kdb>ctrl</kdb> + <kdb>P</kdb>) et commencer la recherche par <code>@</code>. Ou <code>@:</code> pour regrouper les symboles par nature (classes, fonctions, etc). Le &#8220;go to symbole&#8221; marche sur tout le projet avec <kdb>Ctrl</kdb> + <kdb>T</kdb>, mais c&#8217;est lennnnnnnnnnnnt.</li>
<li>De la même manière, on peut aller à un numéro de ligne avec <code><kdb>Ctrl</kdb>+ <kdb>G</kdb></code>. Mais c&#8217;est plus facile de faire un &#8220;go to anywhere&#8221; puis de taper <code>:</code>. Ou depuis un terminal <code>code file.ext:numligne</code></li>
<li><code><kdb>Ctrl</kdb>+ <kdb>U</kdb></code>, aka &#8220;putain nooooooooooooooon, j&#8217;ai fais un <kdb>ctrl</kdb> + <kdb>d</kdb> de trop&#8221;.</li>
<li><kdb>Ctrl</kdb> + <kdb>k</kdb> + <kdb>ctrl</kdb> + <kdb>f</kdb> appliquer le formateur à la sélection. Pour les gens qui ont des TOC.</li>
<li>VSCode a une preview pour le markdown. Facile à lancer depuis le HUD</li>
<li>Une fois que vous avez pris l&#8217;habitude d&#8217;utiliser &#8220;go to definition&#8221; dans le menu contextuel, sachez que <kdb>ctrl</kdb> + clic fait pareil :)</li>
</ul>
<p>Un snippet perso que je rajoute également (dans <code>$HOME/.config/Code/User/snippets/python.json</code>):</p>
<pre lang="javascript">   "wrap_in_try_except": {
        "prefix": "try",
        "body": [
          "try:",
          "\t${0}${TM_SELECTED_TEXT}",
          "except ${1:Exception}:",
          "\t${2:import pdb; pdb.set_trace()}"
        ],
        "description": "Wrap in try/except"
    },</pre>
<p>Ça permet de sélectionner un truc, de taper <code>try</code> puis tab et avoir le tout wrappé dans un <code>try/except</code>.</p>
<h2>Le futur</h2>
<p>Depuis sa sortie, l&#8217;éditeur est en constante amélioration. Les mises à jour sont toujours une excellente surprise, avec des tas de goodies, y compris dans les extensions.</p>
<p>Mais là, dans la dernière <a href="https://code.visualstudio.com/insiders/">version instable</a> (qui a la bonne idée de ne pas overrider la stable à l&#8217;installation), VSCode vient avec <a href="https://code.visualstudio.com/blogs/2017/11/15/live-share">une preview</a> de l&#8217;édition collaborative. Genre Google doc, mais pour le code, et dans tout l&#8217;éditeur.</p>
<p>La partie chiante, c&#8217;est qu&#8217;il faut un compte (Microsoft évidemment), et donc que ça passe par leurs serveurs.</p>
<p>La partie amazing par contre, c&#8217;est que ça envoie du poney nucléaire. L&#8217;ouverture des onglets, l&#8217;écriture, le scroll&#8230; Tout se synchronise proprement. Si on décide de faire sa vie, VSCode désynchronise la navigation, et permet à tout le monde de travailler en parallèle sur le projet (et même optionnellement donner accès à son terminal). Si on veut de nouveau voir la navigation de l&#8217;autre, on peut demander de le suivre à nouveau, et pouf, on suit ce qu&#8217;il fait en live.</p>
<p>Testé avec des clients à des milliers de borne. C&#8217;est bluffant.</p>
<h2>Vous l&#8217;avez compris</h2>
<p><iframe frameborder="0" width="480" height="270" src="//www.dailymotion.com/embed/video/x2tjxy0?queue-enable=false" allowfullscreen allow="autoplay"></iframe></p>


feed_id: http://sametmax.com/?p=24513
title: Once you go black, you never go back 19
uri: Once-you-go-black-you-never-go-back-9-Recently-updated
url: http://sametmax.com/once-you-go-black-you-never-go-back/
content:
<p>L&#8217;indentation obligatoire et l&#8217;existence du <a href="https://www.python.org/dev/peps/pep-0008/">PEP8</a> sont pour moi deux features fondamentales de Python, limitant énormément la quantité de code illisible qu&#8217;on trouve dans la communauté.</p>
<p>Malgré cela, <a href="http://sametmax.com/le-pep8-et-au-dela-par-la-pratique/">le reformatage de code reste une tache courante</a>, et nécessaire, mais un gâchis énorme de temps. D&#8217;abord il faut décider comment on va formater, ce qui en équipe veut dire débat sur le pire sujet qui soit: le goût. Ensuite il faut mettre en place des configurations de linter (<a href="http://flake8.pycqa.org/en/latest/">flake8</a>, <a href="https://www.pylint.org/">pylint</a>, etc), et potentiellement l&#8217;infra qui va avec (<a href="https://tox.readthedocs.io/en/latest/">tox</a>, <a href="http://flake8.pycqa.org/en/latest/user/using-hooks.html">hooks git</a>, CI&#8230;).</p>
<p>Pour cette raison, de nombreux outils de formatage automatique ont vu le jour. Le premier a été <a href="https://github.com/hhatto/autopep8">autopep8</a>, et plus tard <a href="https://yapf.now.sh/">yapf</a> de Google.</p>
<p>Mais ces deux outils ont quelques soucis:</p>
<ul>
<li>Pas facile à faire marcher ou à configurer.</li>
<li>Ne résout pas l&#8217;éternel débat du formatage préféré qui revient dans un meeting chaque année.</li>
<li>Parfois ils ne marchent pas.</li>
<li>Parfois ils changent le sens du code (arg!).</li>
<li>Ils vous font des git diff bien velus.</li>
<li>Ne marche pas avec toutes les versions de Python.</li>
</ul>
<p>Le monde du langage Go a choisi une stratégie différente: la technique du &#8220;ta gueule&#8221;.</p>
<div id="attachment_24516" style="width: 560px" class="wp-caption aligncenter"><a href="media/19233445.62j4Wqo.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/06/62j4Wqo.jpg" class="grouped_elements" rel="tc-fancybox-group24513"><img src="media/19233445.62j4Wqo.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/06/62j4Wqo.jpg" alt="Et aussi: ta gueule" width="550" height="550" class="size-full wp-image-24516" /></a><p class="wp-caption-text">Et aussi: ta gueule</p></div>
<p>Cette technique subtile et raffinée s&#8217;est incarnée dans l&#8217;outil <a href="https://golang.org/cmd/gofmt/">Gofmt</a>, qui est fourni par défaut avec go, et n&#8217;a AUCUN réglage.</p>
<p>Le résultat, tout le monde a fermé sa gueule et a adopté l&#8217;outil.</p>
<p>Est-ce que le formatage est parfait ? Non.</p>
<p>Est-ce qu&#8217;il plaît à tout le monde ? Absolument pas.</p>
<p>Est-ce qu&#8217;il fait fermer sa putain de gueule à tout le monde afin qu&#8217;on puisse enfin retourner à des choses plus importantes comme coder ?</p>
<p>Yes !</p>
<p>Gofmt produit un formatage suffisamment clair et pragmatique, et comme il est fortement ancré dans la communauté, tout le monde est à la même enseigne. Passer d&#8217;un code à un autre est facile. Pas de temps perdu à discuter du style ou à tweaker ses linters. Tout le monde lance <code>go fmt</code> (aka go ferme ta &#8230;) et on passe à autre chose.</p>
<p>Dernièrement facebook a décidé de faire pareil, et à pondu en open source <a href="https://github.com/ambv/black">black</a> (en référence à Henry Ford), un outil de formatage en Python, qui n&#8217;a que 2 réglages. Il suit le PEP8, mais évidemment sa propre interprétation, et ne propose rien d&#8217;autre.</p>
<p>Black a aussi l&#8217;avantage de fournir des diffs assez petits, et surtout, vérifie si l&#8217;<a href="https://docs.python.org/3/library/ast.html">AST</a> change après un reformatage, et annule le cas échéant, garantissant que le sens de votre code n&#8217;est pas altéré.</p>
<p>Est-ce que j&#8217;aime toutes les règles de formatages de black ? Non.</p>
<p>Est-ce que regarder sa sortie me donne parfois envie de me bouffer les couilles parce que franchement, qui pense que c&#8217;est une bonne idée d&#8217;aligner les choses comme ça ? Parfois.</p>
<p>Mais c&#8217;est good enough.</p>
<p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WtXYvTvCS10?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p>Et du coup, l&#8217;adoption de black a été très rapide dans la communauté, et il a été appliqué à heroku, requests, tablib, envoy, clint, fabric 2 et pytest. 4000 stars sur github.</p>
<h2>Installation</h2>
<p>Évidemment, ça se pip install, mais uniquement sur Python 3.6. Black peut checker du code 2.7, mais il lui faut du 3.6 minimum pour exister, donc on l&#8217;installe en parallèle. Évidemment, on peut l&#8217;intégrer à <a href="https://github.com/jgirardet/sublack">ST</a>, <a href="https://github.com/ambv/black/blob/master/plugin/black.vim">Vim</a> ou <a href="https://marketplace.visualstudio.com/items?itemName=joslarson.black-vscode">VSCode</a>. Si votre projet utilise un Python different, il faut donc dans les options faire pointer l&#8217;exécutable vers l&#8217;installation séparée.</p>
<h2>Résultat</h2>
<p>Dans l&#8217;esprit <a href="http://sebsauvage.net/links/?8zEVQw">du lien partagé par Seb</a>, créons un générateur de titre de film porno:</p>
<pre lang="python">

import random

subject_qualifiers = ( "shy", "mature", "busty", "hot", "horny", "ebony", "quiet", "excited", "naughty", "bad", "cheating", "beautifull", "gorgeous", "drunk", "emo", "fat", "chubby", "goth", "lingery wearing", "latex enthousiast", "placid", "energic", 'slutty', 'sweaty', 'curvy', )

subjects =(
    'teen',
    'doll',
    'brunette',
    'blonde',
    'midget',
    'milf',
    'bitch',
    'babe',
    'sister',
    'step-mom',
    'vixen',
    'secretary',
    'real estate agent',
    'teacher',
    'student',
    'schoolgirl',
    'cheer leader',
    'asian tourist',
    'babysitter',
    'ex girlfriend',
    'nurse',
    'squirtter',
    'model',
    'granny',
    'furry',
)

actions = (
        "recieves anal",
        "get busted",
        "driven to bukakke",
        "taught double penetration",
        "fucked hard",
        'gently chocked',
        'punished',
        'forced into blow job',
        'pounded',
        'creampied',
        'ass raped',
        "eaten",
        "get her pussy wet",
        "shamed",
        "get an orgasm for the first time",
        'lead to loud climax',
        'offered best sex of her life',
        'worn out',
        'cured from boredom',
        'warmed up',
        'loved in and out',
        'generously oiled',
        'shocked and impressed',
        'decieved into giving it',
        'woke up roughly',
        'get sexy massage',
        'ridden to exhaustion',
        'turned into a lavish slave',
        'never submit to torture',
        'rebels against abuses',
        'taken in every possible way',
        'enjoy the 10 inches provided',
)

actors = (
        "pawn shop owner",
    "corrupted cop",
    "dirty plumber",
    "big ass nigga",
    "sport coach"
    "her boss",
    "twisted psychiatrist",
    "ripped doctor",
    "crispy fire fighter",
    "smug playboy",
    "skinny geek",
    "eccentric millionaire",
    "airplane pilot",
    "movie star",
    'football team',
    'her big brother',
    'security guard',
    'hairy beast',
    'wasted guitard player',
    'hung indian immigrant',
    'a guy twice her size',
    '17 guys in a row',
    'her ideal man',
    'her secret prince charming',
    'weirdo albinos',
    'muscle giant',
    'the worst cook ever',
    'cable man',
    'more men that she can count',
    'two friendly brothers',
    'enrike strongsteel'
)

contexts = (
    "on the beach","in a cheap motel","in the back of a van",
    "in airplane toilets", "for hours", "to pay back her depts",
    "for a stupid mistake", "and it gets better", "and ask for more",
    "because she could", "in exchange for a favor",
    "right next to her boyfriend", "as a reward",
    "hopping to get him back", "caught on security cam", "every monday",
    "in a barn", "but that's not all", 'but she has a secret',
    "and she has a dick too", 'before inviting her friend over',
    'while her father is watching', 'with her ', "while auditing for a role",
    "to get her job back", "for an interview", "in exclusive sex tape",
    "again and again", ", begging to stop", "for a change", "for chrismas",
    "in public", 'in a back alley', "during a concert", 'on her death bed'
)

punctuation = ('','!','!!','...')

def get_title(subject_qualifiers, subjects, actions, actors, contexts) :


    qualifier = random.choice(subject_qualifiers)
    subject = random.choice(subjects)
    action = random.choice(actions)
    actor = random.choice(actors)
    context = random.choice(contexts)

    return f"{qualifier} {subject} {action} by {actor} {context}" .capitalize()


if __name__ == "__main__":
    print(get_title(subject_qualifiers = subject_qualifiers, subjects=subjects,
                    actions=actions, actors=actors, contexts=contexts))
</pre>
<p>Usage:</p>
<pre lang="bash">$ python3.6 porn_title_generator.py
Chubby model loves bukakke by skinny geek during a concert
$ python3.6 porn_title_generator.py
Busty bitch rebel against abuses by security guard but she has a secret
$ python3.6 porn_title_generator.py
Lingery wearing student creampied by weirdo albinos on the beach
$ python3.6 porn_title_generator.py
Horny bitch offered best sex of her life by hairy beast in airplane toilets
$ python3.6 porn_title_generator.py
Emo blonde punished by airplane pilot on the beach
$ python3.6 porn_title_generator.py
Quiet squirtter lead to loud climax by wasted guitard player while auditing for a role
$ python3.6 porn_title_generator.py
Emo babysitter get her pussy wet by football team caught on security cam
$ python3.6 porn_title_generator.py
Busty asian tourist taken in every possible way by muscle giant and she has a dick too
$ python3.6 porn_title_generator.py
Placid milf ass raped by muscle giant in a back alley</pre>
<div id="attachment_24515" style="width: 686px" class="wp-caption aligncenter"><a href="media/edabb21e.USwuxJQ.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/06/USwuxJQ.jpg" class="grouped_elements" rel="tc-fancybox-group24513"><img src="media/edabb21e.USwuxJQ.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/06/USwuxJQ.jpg" alt="Je soupçonne un coup des frères Markov" width="676" height="498" class="size-full wp-image-24515" /></a><p class="wp-caption-text">Je soupçonne un coup des frères Markov</p></div>
<p>On applique black, zero réglage, usage simplissime:</p>
<pre lang="bash">$ black . # appel recursif, modification in place par défaut</pre>
<p>Le résultat.</p>
<pre lang="python">
import random

subject_qualifiers = (
    "shy",
    "mature",
    "busty",
    "hot",
    "horny",
    "ebony",
    "quiet",
    "excited",
    "naughty",
    "bad",
    "cheating",
    "beautifull",
    "gorgeous",
    "drunk",
    "emo",
    "fat",
    "chubby",
    "goth",
    "lingery wearing",
    "latex enthousiast",
    "placid",
    "energic",
    "slutty",
    "sweaty",
    "curvy",
)

subjects = (
    "teen",
    "doll",
    "brunette",
    "blonde",
    "midget",
    "milf",
    "bitch",
    "babe",
    "sister",
    "step-mom",
    "vixen",
    "secretary",
    "real estate agent",
    "teacher",
    "student",
    "schoolgirl",
    "cheer leader",
    "asian tourist",
    "babysitter",
    "ex girlfriend",
    "nurse",
    "squirtter",
    "model",
    "granny",
    "furry",
)

actions = (
    "recieves anal",
    "get busted",
    "driven to bukakke",
    "taught double penetration",
    "fucked hard",
    "gently chocked",
    "punished",
    "forced into blow job",
    "pounded",
    "creampied",
    "ass raped",
    "eaten",
    "get her pussy wet",
    "shamed",
    "get an orgasm for the first time",
    "lead to loud climax",
    "offered best sex of her life",
    "worn out",
    "cured from boredom",
    "warmed up",
    "loved in and out",
    "generously oiled",
    "shocked and impressed",
    "decieved into giving it",
    "woke up roughly",
    "get sexy massage",
    "ridden to exhaustion",
    "turned into a lavish slave",
    "never submit to torture",
    "rebels against abuses",
    "taken in every possible way",
    "enjoy the 10 inches provided",
)

actors = (
    "pawn shop owner",
    "corrupted cop",
    "dirty plumber",
    "big ass nigga",
    "sport coach" "her boss",
    "twisted psychiatrist",
    "ripped doctor",
    "crispy fire fighter",
    "smug playboy",
    "skinny geek",
    "eccentric millionaire",
    "airplane pilot",
    "movie star",
    "football team",
    "her big brother",
    "security guard",
    "hairy beast",
    "wasted guitard player",
    "hung indian immigrant",
    "a guy twice her size",
    "17 guys in a row",
    "her ideal man",
    "her secret prince charming",
    "weirdo albinos",
    "muscle giant",
    "the worst cook ever",
    "cable man",
    "more men that she can count",
    "two friendly brothers",
    "enrike strongsteel",
)

contexts = (
    "on the beach",
    "in a cheap motel",
    "in the back of a van",
    "in airplane toilets",
    "for hours",
    "to pay back her depts",
    "for a stupid mistake",
    "and it gets better",
    "and ask for more",
    "because she could",
    "in exchange for a favor",
    "right next to her boyfriend",
    "as a reward",
    "hopping to get him back",
    "caught on security cam",
    "every monday",
    "in a barn",
    "but that's not all",
    "but she has a secret",
    "and she has a dick too",
    "before inviting her friend over",
    "while her father is watching",
    "with her ",
    "while auditing for a role",
    "to get her job back",
    "for an interview",
    "in exclusive sex tape",
    "again and again",
    ", begging to stop",
    "for a change",
    "for chrismas",
    "in public",
    "in a back alley",
    "during a concert",
    "on her death bed",
)

punctuation = ("", "!", "!!", "...")


def get_title(subject_qualifiers, subjects, actions, actors, contexts):

    qualifier = random.choice(subject_qualifiers)
    subject = random.choice(subjects)
    action = random.choice(actions)
    actor = random.choice(actors)
    context = random.choice(contexts)

    return f"{qualifier} {subject} {action} by {actor} {context}".capitalize()


if __name__ == "__main__":
    print(
        get_title(
            subject_qualifiers=subject_qualifiers,
            subjects=subjects,
            actions=actions,
            actors=actors,
            contexts=contexts,
        )
    )

</pre>
<p>L&#8217;indentation est revue et normalisée vers 4 espaces, les espacements et sauts de ligne sont rééquilibrés (<a href="https://github.com/ambv/black#line-length">limite de caractères à 88 </a>), les quotes deviennent toutes &#8216;&#8221;&#8216;. C&#8217;est lisible. Le code marche toujours.</p>
<p>Problem solved.</p>


feed_id: http://sametmax.com/?p=24534
title: Go to (in asyncio) considered harmful 26
uri: Go-to-(in-asyncio)-considered-harmful-4-Recently-updated
url: http://sametmax.com/go-to-in-asyncio-considered-harmful/
content:
<p>Dijkstra était un intellectuel pédant, mais quand il a écrit cette lettre célèbre, il a comme souvent mis le doigt sur un truc fondamental. Et quand l&#8217;auteur de <a href="https://github.com/python-trio/trio">Trio</a>, une stack toute neuve concurrente d&#8217;<code>asyncio</code>, <a href="https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/">lui a fait écho</a> 50 ans plus tard, ça a beaucoup discuté sur les mailing lists et les bugs trackers.</p>
<p>Nathaniel J. Smith, le dev susnommé, en a profité pour introduire une nouvelle primitive, actuellement surnommée <a href="http://trio.readthedocs.io/en/latest/reference-core.html#nurseries-and-spawning">la nursery</a>, pour répondre au problème. Une idée visiblement tellement bonne que notre Yury préféré <a href="https://twitter.com/1st1/status/989198832910192640">a décidé</a> de la porter à <code>asyncio</code>. La boucle d&#8217;événements est bouclée, si je puis dire.</p>
<p>Mais une autre chose intéressante en découle : on a mis en lumière la présence d&#8217;un <a href="https://en.wikipedia.org/wiki/Goto">goto</a> dans asyncio, et qu&#8217;il y a de bonnes pratiques, <a href="https://github.com/python/asyncio/issues/477#issuecomment-269038238">validées par Guido himself</a>, pour coder avec cette lib pour éviter les douleurs.</p>
<h2>What the fuck are you talking about ?</h2>
<p>Le problème du <code>goto</code>, c&#8217;est que l&#8217;instruction permet d&#8217;aller de n&#8217;importe où à n&#8217;importe où. Cela rend le flux du programme très dur à suivre. Pour éviter cela, on a catégorisé les usages clean du <code>goto</code>: répéter une action, changer de comportement en fonction d&#8217;un test, sortir d&#8217;un algo en cas de problème, etc. Et on en a fait des primitives : les <code>if</code>, les <code>while</code>, les exceptions&#8230; Dans les langages les plus modernes, on a carrément viré le <code>goto</code> pour éviter les abus et erreurs. Joie.</p>
<p>Dans <code>asyncio</code>, le &#8220;goto&#8221; en question se trouve quand on veut lancer des tâches en arrière plan, comme ceci :</p>
<pre lang="python">import asyncio as aio
loop = aio.get_event_loop()
aio.ensure_future(foo())  # GOTO !
aio.ensure_future(bar())  # GOTO !
loop.run_forever()</pre>
<p>Le problème d&#8217;<code>ensure_future()</code> est multiple:</p>
<ul>
<li>Comme son nom l&#8217;indique, cette fonction retourne un objet&#8230; <code>Task</code>. Ca n&#8217;a rien à voir, mais je tenais à dire à quel point c&#8217;était con de l&#8217;avoir nommé ainsi (même si techniquement, <code>Task</code> hérite de <code>Future</code>).</li>
<li>Cette ligne ne garantit en aucun cas que <code>foo()</code> ou <code>bar()</code> seront terminées à une zone précise du code. Tout au plus que tuer la boucle tue les taches. Leur flux d’exécution est complètement freestyle et décorrélé de tout le reste du programme, ainsi que de l&#8217;une de l’autres. Si ces coroutines font des <code>await</code>, on peut basculer de n&#8217;importe où du programme vers elles et inversement à tout moment. <code>goto</code></li>
<li>Cette ligne schedule le démarrage de <code>foo()</code> et <code>bar()</code> dès que la boucle peut les lancer. Ici la boucle ne tourne pas encore. Plus le programme est complexe, plus il va devenir difficile de savoir à quelle étape logique les coroutines vont démarrer.</li>
</ul>
<p>En prime <code>run_forever()</code> est un piège à con, car les exceptions qui arrivent dans la boucle sont logguées, mais ne font pas crasher le programme, ce qui rend le debuggage super rude, même avec <a href="https://docs.python.org/3/library/asyncio-dev.html#debug-mode-of-asyncio">debug mode</a> activé (dont de toute façon personne ne soupçonne l&#8217;existence).</p>
<h2>La solution asyncio</h2>
<pre lang="python">
import asyncio as aio
loop = aio.get_event_loop()
loop.run_until_complete(aio.gather(foo(), bar())
</pre>
<p>En plus d&#8217;être plus court, les exceptions vont faire planter le programme, la loop s&#8217;arrêtera quand les coroutines auront fini leur taff, leur flux a un début et une fin encapsulés par le <code>gather()</code>. Ceci est encore plus visible si on met le même code à l&#8217;intérieur d&#8217;une coroutine à l&#8217;intérieur d&#8217;une coroutine à l&#8217;intérieur d&#8217;une coroutine plutôt qu&#8217;à la racine du programme. En effet dans un exemple si simple, on se borne au démarrage et à l&#8217;arrêt de la boucle. Mais je suis paresseux.</p>
<p>Donc, c&#8217;est la bonne pratique, mais tout le monde ne le sait pas.</p>
<p>Pardon, correction.</p>
<p>Tous les devs Python ne connaissent pas <code>asyncio</code>. Parmi ceux qui connaissent <code>asyncio</code>, une petite partie comprend comme ça marche.</p>
<p>Dans ce lot rikiki, un pouillième sait que c&#8217;est la bonne pratique.</p>
<p>En fait, <code>gather()</code> est probablement la fonction la plus importante d&#8217;<code>asyncio</code>, et pourtant elle apparaît à peine dans la doc. C&#8217;est la malédiction d&#8217;<code>asyncio</code>, une lib que tout le monde attendait pour propulser Python dans la league des langages avec frameworks modernes, mais qui commence à peine à devenir utilisable par le commun des mortel en 2018. Et encore.</p>
<p>Il ne faut jamais utiliser <code>ensure_future()</code> à moins de vouloir attacher un callback à la main dessus, ce qui n&#8217;est probablement jamais ce que vous voulez à cette époque merveilleuse ou existe <code>async/await</code>. <code>ensure_future()</code> est un <code>goto</code>, <code>gather()</code> est un concept de plus haut niveau.</p>
<p>Mais deux problèmes demeurent&#8230;</p>
<p>Contrairement au <code>goto</code> banni de Python, <code>ensure_future()</code> est là, et va rester. Donc n&#8217;importe quel connard peut dans un code ailleurs vous niquer profond, et en tâche de fond.</p>
<p><code>ensure_future()</code> (ou son petit frère <code>EventLoop.create_task()</code>) reste le seul moyen valable pour lancer une tâche, faire quelque chose, lancer une autre tâche, puis enfin faire un <code>gather()</code> sur les deux tâches:</p>
<pre lang="python">
async def grrr():
    task1 = aio.ensure_future(foo())
    # faire un truc pendant que task1 tourne
    task2 = aio.ensure_future(bar())
    # faire un truc pendant que task1 et task2 tournent
    # On s'assure que tout se rejoint à la fin:
    await aio.gather(task1, task2)
</pre>
<p>Et puis, faire une pyramide de <code>gather()</code> dans tout son code pour s&#8217;assurer que tout va bien de haut en bas, c&#8217;est facile à rater.</p>
<h2>La nursery : la solution de trio</h2>
<p>Une nursery agit comme un scope qui pose les limites du cycle de vie des tâches qui lui sont attachées. C&#8217;est un <code>gather()</code>, sous stéroide, et avec une portée visuellement claire:</p>
<pre lang="python">
async def grrr():
    async with trio.open_nursery() as nursery:
        task1 = nursery.start_soon(foo)
        # faire un truc pendant que task1 tourne
        task2 = nursery.start_soon(bar)
        # faire un truc pendant que task1 et task2 tournent
</pre>
<p>Les taches sont garanties, à la sortie du <code>with</code>, de se terminer. Le <code>ensure_future()</code> n&#8217;a pas d&#8217;équivalent en trio, et donc aucun moyen de lancer un truc dans le vent sans explicitement lui passer au moins une nursery à laquelle on souhaite l&#8217;attacher.</p>
<p>Résultat, on ne peut plus faire de <code>goto</code>, et le flux du program est clair et explicite.</p>
<p>Notez que, tout comme <code>if</code> et <code>while</code> ne permettaient rien qu&#8217;un utilisateur soigneux de <code>goto</code> ne pouvait faire, la nursery ne permet rien qu&#8217;un utilisateur soigneux de <code>ensure_future()</code> ne peut faire. Mais ça force un ensemble de bonnes pratiques.</p>
<p>Évidemment, on peut ouvrir une nursery dans un bloc d&#8217;une autre nursery, ce qui permet d&#8217;imbriquer différentes portées, comme on le ferait avec un <code>begin()</code> de transaction de base de données. Or, une exception à l&#8217;intérieur d&#8217;une nursery <a href="http://sametmax.com/gestion-des-erreurs-en-python/">bubble</a> naturellement comme toute exception Python, et stoppe toutes les tâches de la nursery encore en train de tourner. Alors qu&#8217;avec <asyncio>asyncio</asyncio> vous l&#8217;avez dans le cul.</p>
<p>En définitive, c&#8217;était la pièce manquante. La moitié du boulot avait était faite quand on a introduit un moyen de gérer des tâches asynchrones qui dépendent les unes des autres, en remplaçant les callbacks par un truc de haut niveau : <code>async/await</code>. Il restait la gestion des tâches en parallèle qui se faisait encore selon les goûts et compétences de chacun, mais la nursery va remplir ce vide. </p>
<p>Cela devrait être intégré à <code>asyncio</code> en Python 3.8, soit une bonne année et demie pour ceux qui ont la chance de pouvoir faire du bleeding edge.</p>
<p>Comme certains ne voudront pas attendre, je vous ai fait un <a href="https://0bin.net/paste/V5KyhAg-2i5EOyoK#dzBvhdCVeFy8Q2xNcxXyqwtyQFgkxlKI3u5QG0buIcT">POC</a> qui vous montre comment ça pourrait marcher. Mais cette version ne sera jamais utilisée. En effet, elle intercepte <code>ensure_future()</code> (en fait le  <code>create_task()</code> sous-jacent) pour attacher son résultat à la nursery en cours, évitant tout effet <code>goto</code>, et ça péterait trop de code existant. Mon pognon est plutôt sur un gros warning émis par Python quand on fait une gotise.</p>
<p>Dernier mot: s&#8217;il vous plaît, <strong><a href="https://github.com/python-trio/trio/issues/504">allez voter</a> pour change le nom de nursery</strong>. C&#8217;est beaucoup trop long à taper pour un truc qu&#8217;on va utiliser tout le temps.</p>


feed_id: http://sametmax.com/?p=24605
title: Super article invité sur Trio que l’auteur a oublié de titrer 11
uri: Super-article-invité-sur-Trio-que-l-auteur-a-oublié-de-titrer-5
url: http://sametmax.com/super-article-invite-sur-trio-que-lauteur-a-oublie-de-titrer/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/touilleMan">touilleMan</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>C&#8217;est bon vous avez cédé à la hype ?</p>
<p>Après un n-ème talk sur asyncio vous avez été convaincu que tout vos sites webs doivent être recodé dans cette techno ? Oui, surtout celui de la mairie de Gaudriole-sur-Gironde avec ses 50 visiteurs/jour, Django ça scalera pas et vous aurez sûrement besoin de websockets à l&#8217;avenir.</p>
<p>Et puis là pan ! En commençant à utiliser asyncio on se rend compte que ça va pas être aussi marrant que ce que vous a vendu l&#8217;enfoiré de hipster dans son talk avec son exemple de crawler web en 20 lignes :</p>
<ul>
<li>la doc de asyncio fait 50 putain de pages, <a href="http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/">même les plus grands déclarent ne rien y comprendre</a></li>
<li>pdb est aux fraises, un step-over sur un <code>await</code> vous envoi à perpet&#8217; dans l&#8217;event loop</li>
<li>il faut passer l&#8217;event loop en tant qu&#8217;argument à chaque fonction, évidemment vous n&#8217;allez pas le faire et utiliser <code>get_event_loop()</code> à la place. Et ça va merder sévère à un moment (typiquement quand vous ajouterez des tests non triviaux), et vous allez devoir corriger tout votre code.</li>
<li>régulièrement une stacktrace d&#8217;une coroutine ayant crashé dégueule de stdout sans que le programme ne bronche, autant de je m&#8217;en foutisme on se croirait revenu en PHP !</li>
<li>parlons-en de la stacktrace ! Impossible de savoir d&#8217;où vient la coroutine, encore une fois on nous renvoi dans les méandres de l&#8217;event loop.</li>
<li>Et pour initialiser/finaliser proprement votre système alors là c&#8217;est la fête totale</li>
</ul>
<p>Je ne parle même pas des soucis ceinture-noir-2ème-dan du genre high-water mark qui vous tomberons dessus une fois l&#8217;appli en prod.</p>
<p>Lourd est le parpaing de la réalité sur la tartelette aux fraises de nos illusions&#8230;</p>
<h2>1 &#8211; Pourquoi c&#8217;est (de) la merde ?</h2>
<p>Pour faire simple asyncio a été pensé à la base comme une tentative de standardisation de l&#8217;écosystème asynchrone Python où chaque framework (Twisted et Tornado principalement) était incompatible avec les autres et devait re-créer son écosystème de zéro.</p>
<p>C&#8217;était la bonne chose à faire à l&#8217;époque, ça a eu beaucoup de succès (Twisted et Tornado sont maintenant compatible asyncio), ça a donné une killer-feature pour faire taire les rageux au sujet de Python 3 et ça a créé une émulsion formidable concernant la programmation asynchrone en Python.<br />
Mais dans le même temps ça a obligé cette nouvelle lib à hériter des choix historiques des anciennes libs : les callbacks.</p>
<p>Pour faire simple un framework asynchrone c&#8217;est deux choses :</p>
<ul>
<li>une grosse boucle infinie (la fameuse « event loop ») qui a configuré les appels d&#8217;IO au kernel en mode non-bloquant et qui poll ceux-ci en continu</li>
<li>un mécanisme pour garder trace de quel bout de code exécuter quand une IO donnée aura été terminée</li>
</ul>
<p>Concernant le 2ème point, cela veut dire que si on a une fonction synchrone comme ceci :</p>
<pre lang="python">def listen_and_answer(sock):
    print('start')
    data = sock.read()
    print('working with %s' % data)
    sock.write('ok')
    print('done')
</pre>
<p>Il faut trouver un moyen pour la découper en une série de morceaux de codes et d&#8217;IO.</p>
<p>Il y la façon « javascript », où on découpe à la main comme un compilo déroulerai une boucle :</p>
<pre lang="python">def listen_and_answer(sock):
    print('start')

    def on_listen(data):
        print('working with %s' % data)

        def on_write(ret):
            print('done')

        sock.write('ok', on_write)

    sock.read(on_listen)
</pre>
<p>Et là j&#8217;ai fait la version simple sans chercher à gérer les exceptions et autres joyeusetés. Autant dire que quand un vieux dev Twisted vous dit le regard vide et la voix chevrotante qu&#8217;il a connu l&#8217;enfer, ne prenez pas ses déclarations à la légère.</p>
<p>Sinon la façon async/await si chère à asyncio :</p>
<pre lang="python">async def listen_and_answer(sock):
    print('start')
    data = await sock.read()
    print('working with %s' % data)
    await sock.write('ok')
    print('done')
</pre>
<p>C&#8217;est clair, c&#8217;est propre, la gestion des exceptions est totalement naturelle, bref c&#8217;est du Python dans toute sa splendeur.<br />
Sauf que non, tout ça n&#8217;est qu&#8217;un putain d&#8217;écran de fumée : pour être compatible avec Twisted&amp;co sous le capot asyncio fonctionne avec des callbacks.</p>
<p>Vous vous souvenez de cette sensation de détresse mêlée d’hilarité devant une stacktrace d&#8217;un projet Javascript lambda d&#8217;où vous ne reconnaissez que la première ligne ? C&#8217;est ça les callbacks, et c&#8217;est ça que vous avez dans asyncio.</p>
<p>Concrètement le soucis vient du fait qu&#8217;une callback n&#8217;est rien d&#8217;autre qu&#8217;une fonction passée telle qu&#8217;elle sans aucune information quant à d&#8217;où elle vient. De fait impossible pour l&#8217;event loop asynchrone de reconstruire une callstack complète à partir de cela.<br />
Heureusement async/await permettent à python de conserver ces informations de fonction appelante ce qui limite un peu le problème avec asyncio.<br />
Toutefois en remontant suffisamment haut on finira toujours avec une callback quelque part. Et vous savez qui a l&#8217;habitude de remonter aussi haut que nécessaire ? Les exceptions.</p>
<pre lang="python">import asyncio
import random

async def succeed(client_writer):
    print('Lucky guy...')
    # Googlez "ayncio high water mark" pour comprender pourquoi c'est
    # une idée à la con de ne pas avoir cette methode asynchrone
    client_writer.write(b'Lucky guy...')

async def fail(client_writer):
    raise RuntimeError('Tough shit...')

async def handle_request_russian_roulette_style(client_reader, client_writer):
    handlers = (
        succeed,
        succeed,
        succeed,
        fail,
    )
    await handlers[random.randint(0, 3)](client_writer)
    client_writer.close()

async def start_server():
    server = await asyncio.start_server(
        handle_request_russian_roulette_style,
        host='localhost', port=8080)
    await server.wait_closed()

asyncio.get_event_loop().run_until_complete(start_server())
</pre>
<p>Maintenant si on lance tout ça et qu&#8217;on envoie des <code>curl localhost:8080</code> on va finir avec:</p>
<pre lang="bash">$ python3 russian_roulette_server.py
Lucky guy...
Lucky guy...
Task exception was never retrieved
future:  exception=RuntimeError('Tough shit...',)&gt;
Traceback (most recent call last):
  File "ex.py", line 18, in handle_request_russian_roulette_style
    await handlers[random.randint(0, 3)](client_writer)
  File "ex.py", line 9, in fail
    raise RuntimeError('Tough shit...')
RuntimeError: Tough shit...
Lucky guy...
Task exception was never retrieved
future:  exception=RuntimeError('Tough shit...',)&gt;
Traceback (most recent call last):
  File "ex.py", line 18, in handle_request_russian_roulette_style
    await handlers[random.randint(0, 3)](client_writer)
  File "ex.py", line 9, in fail
    raise RuntimeError('Tough shit...')
RuntimeError: Tough shit...
</pre>
<p>Le problème saute aux yeux: <code>asyncio.start_server</code> gère sa tambouille avec des callbacks et se retrouve bien embêté quand notre code remonte une exception. Du coup il fait au mieux en affichant la stacktrace et en faisant comme si de rien n&#8217;était. C&#8217;est peut-être le comportement qu&#8217;on attend d&#8217;un serveur web (encore que&#8230; si aviez configuré logging pour envoyer dans un fichier vous êtes bien baïzay) mais il existe des tonnes de usecases pour lesquels ça pose problème (et de toute façon on n&#8217;a vu que la partie émergée de l&#8217;iceberg d&#8217;emmerdes qu&#8217;est la programmation asynchrone).</p>
<p>Bref, si vous voulez en savoir plus, allez lire <a href="https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/">ce post</a>, d&#8217;ailleurs allez lire tous les posts du blog, ce mec est un génie.</p>
<h2>2 &#8211; Trio, une façon de faire de l&#8217;asynchrone</h2>
<p>Ce mec en question, c&#8217;est Nathaniel J. Smith et il a eu la très cool idée de créer sa propre lib asynchrone pour Python: <a href="https://trio.readthedocs.io/">Trio</a></p>
<p>L&#8217;objectif est simple: rendre la programmation asynchrone (presque) aussi simple que celle synchrone en s&#8217;appuyant sur les nouvelles fonctionnalités offertes par les dernières versions de Python ainsi qu&#8217;un paradigme de concurrence innovant. Cette phrase est digne d&#8217;un marketeux, vous avez le droit de me cracher à la gueule.</p>
<p>Concrètement ce que ça donne:</p>
<pre lang="python"># pip install trio asks beautifulsoup4
import trio
import asks
import bs4
import re


# Asks est un grosso modo requests en asynchrone, vu qu'il supporte trio et curio
# (une autre lib asynchrone dans le même style), il faut donc lui dire lequel utiliser
asks.init('trio')


async def recursive_find(url, on_found, depth=0):
    # On fait notre requête HTTP en asynchrone
    rep = await asks.get(url)
    print(f'depth {depth}, try {url}...')

    # On retrouve le corps de l'article grace à beautiful soup
    soup = bs4.BeautifulSoup(rep.text, 'html.parser')
    body = soup.find('div', attrs={"id": 'mw-content-text'})

    # On cherche notre point Godwin
    if re.search(r'(?i)hitler|nazi|adolf', body.text):
        on_found(url, depth)

    else:
        async with trio.open_nursery() as nursery:
            # On retrouve tous les liens de l'article et relance le recherche
            # de manière récursive
            for tag in body.find_all('a'):
                if tag.has_attr('href') and tag.attrs['href'].startswith('/wiki/'):
                    child_link = 'https://en.wikipedia.org' + tag.attrs['href']
                    # On créé une nouvelle coroutine par lien à crawler
                    nursery.start_soon(recursive_find, child_link, on_found, depth+1)


async def godwin_find(url):
    results = []

    with trio.move_on_after(10) as cancel_scope:
        def on_found(found_url, depth):
            results.append((found_url, depth))
            cancel_scope.cancel()

        await recursive_find(url, on_found)

    if results:
        found_url, depth = results[0]
        print(f'Found Godwin point in {found_url} (depth: {depth})')
    else:
        print('No point for this article')


trio.run(godwin_find, 'https://en.wikipedia.org/wiki/My_Little_Pony')
</pre>
<p>L&#8217;idée de ce code est, partant d&#8217;un article wikipedia, de crawler ses liens récursivement jusqu&#8217;à ce qu&#8217;on trouve un article contenant des mots clés.</p>
<p>Au niveau des trucs intéressants:</p>
<pre lang="python">async with trio.open_nursery() as nursery:
    for tag in body.find_all('a'):
        if tag.has_attr('href') and tag.attrs['href'].startswith('/wiki/'):
            child_link = 'https://en.wikipedia.org' + tag.attrs['href']
            nursery.start_soon(recursive_find, child_link, on_found, depth+1)
</pre>
<p>En trio, une coroutine doit forcément être connectée à une nurserie. Cela permet deux choses:</p>
<ul>
<li>Rattacher la coroutine à sa coroutine parente, de cette façon (et vu que trio est implémenté intégralement en utilisant async/await au lieu de callbacks), on a donc une stacktrace claire et une exception sera toujours propagée jusqu&#8217;à la racine du programme si il le faut.</li>
<li>Borner la durée de vie de la coroutine. La nurserie est un context manager asynchrone, une fois qu&#8217;on arrive à la fin du <code>async with</code>, la nursery bloque tant que toutes les coroutines qu&#8217;elle gère n&#8217;ont pas terminé. Si une coroutine raise une exception, la nursery va pouvoir cancel les autres coroutines avant de re-raise l&#8217;exception en question (cf. le point précédent)</li>
</ul>
<p>Quel intérêt à borner la durée de vie des coroutines ? Si on avait voulu écrire un truc équivalent en asyncio on aurait sans doute utilisé <code>asyncio.gather</code>:</p>
<pre lang="python">coroutines = [recursive_find(link) for link in links]
await asyncio.gather(coroutines)
</pre>
<p>Maintenant on fait tourner ce code avec une connection internet un peu faiblarde (au hasard sur la box Orange de Sam ces temps ci&#8230;) les ennuis auraient commencé dès qu&#8217;une requête http aurait timeout.<br />
L&#8217;exception de timeout aurait été récupérée par <code>asyncio.gather</code> qui l&#8217;aurait relancé sans pour autant fermer les autres coroutines qui auraient continué à crawler wikipedia en créant des centaines de coroutines (oui <code>recursive_find</code> est un peu bourrin).<br />
De fait si on se place dans le cas d&#8217;un code tournant longtemps (typiquement on a un serveur web qui a lancé notre code dans le cadre du traitement d&#8217;une requête entrante) on va avoir bien du mal à retrouver l&#8217;état ayant mené à ce bordel.</p>
<p>Du coup en trio la seule solution pour avoir une coroutine qui survit à son parent c&#8217;est de lui passer une nursery en paramètre:</p>
<pre lang="python">async def work(sleep_time, nursery):
    await trio.sleep(sleep_time)
    print('work done !')
    # Je vous ai dit qu'une nurserie contient automatiquement un cancel scope ?
    nursery.cancel_scope.cancel()

async def work_generator(nursery):
    print('bootstrapping...')
    await trio.sleep(1)
    for sleep_time in range(10):
        nursery.start_soon(work, sleep_time, nursery)

async def stop_a_first_work_done():
    async with trio.open_nursery() as nursery:
        await work_generator(nursery)
        print('Waiting for a work to finish...')
</pre>
<p>Un autre truc cool:</p>
<pre lang="python">with trio.move_on_after(10) as cancel_scope:
    def on_found(found_url, depth):
        results.append((found_url, depth))
        cancel_scope.cancel()

    await recursive_find(url, on_found)
</pre>
<p>Vu qu&#8217;en trio on se retrouve avec un arbre de coroutines, il est très facile d&#8217;appliquer des conditions sur un sous-ensemble de l&#8217;arbre. C&#8217;est le rôle des cancel scope.<br />
Comme pour les nursery, les cancel scope sont des contexts managers (mais synchrone ceux-ci). On peut les configurer avec un timeout, une deadline, ou bien tout simplement les annuler manuellement via <code>cancel_scope.cancel()</code>.</p>
<p>Dans notre exemple, on définit un scope dont on sortira obligatoirement au bout de 10s. Pour éviter d&#8217;attendre pour rien, on annule le scope explicitement dans la closure appelée quand un résultat est trouvé.<br />
Vu que les nurseries définies à chaque appel de <code>recursive_find</code> se trouvent englobées par notre cancel scope, elles seront automatiquement détruites (et toutes les coroutines qu&#8217;elles gèrent avec).</p>
<p>Pour faire la même chose avec asyncio bonne chance:</p>
<ul>
<li>soit on passe un argument de timeout à notre appel pour récupérer la requête HTTP, mais dans ce cas pour peu que chaque requête soit individuellement plus courte que le timeout on ne s&#8217;arrêtera jamais</li>
<li>soit on gère à la mano le temps à coup de <code>time.monotonic()</code> en passant le temps restant autorisé aux coroutines filles. Bonjour la gueule du code.</li>
</ul>
<p>En plus <a href="https://vorpus.org/blog/timeouts-and-cancellation-for-humans/">comme en parlait un mec</a> (décidemment !), la gestion du timeout dans une socket tcp est foireuse, il suffit de recevoir un paquet (et une requête entière peut contenir beaucoup de paquets !) pour que le timeout soit remis à zéro. Donc encore une fois pas de garanties fortes quant à quand le code s&#8217;arrêtera.</p>
<h2>3 &#8211; <strong>Eeeeet c&#8217;est tout !</strong></h2>
<p>Au final la doc de l&#8217;api de trio pourrait tenir sur l&#8217;étiquette de mon slip: pas de promise, de futurs, de tasks, de pattern Protocol/Transport legacy. On se retrouve juste avec la sainte trinité (j&#8217;imagine que c&#8217;est de là que vient le nom) async/await, nursery, cancel scope.</p>
<p>Et évidemment maintenant, l&#8217;enfoiré de hipster qui vous vend une techno à coup de whao effect avec un crawler asynchrone de 20 lignes c&#8217;est moi&#8230;</p>
<p>Remarquez si vous préférez la version longue je vous conseil <a href="https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/">cet excellent article</a> de Nathaniel (je vous ai dit que ce mec était un génie ?).</p>
<h2>4 &#8211; L&#8217;écosystème</h2>
<p>C&#8217;est là où on se rend compte que asyncio est malgré ses lacunes une super idée: il a suffit d&#8217;écrire une <a href="https://github.com/python-trio/trio-asyncio">implémentation de l&#8217;event loop asyncio en trio</a> pour pouvoir utiliser tout l&#8217;écosystème asyncio (ce qui inclus donc Twisted et Tornado, snif c&#8217;est beau !).</p>
<p>Allez pour le plasir un exemple d&#8217;utilisation de asyncpg depuis trio:</p>
<pre lang="python">import trio_asyncio
import asyncpg


class TrioConnProxy:
    # Le décorateur permet de marquer la frontière entre trio et asyncio
    @trio_asyncio.trio2aio
    async def init(self, url):
        # Ici on est donc dans asyncio
        self.conn = await asyncpg.connect(url)

    @trio_asyncio.trio2aio
    async def execute(self, *args):
        return await self.conn.execute(*args)

    @trio_asyncio.trio2aio
    async def fetch(self, *args):
        return await self.conn.fetch(*args)


async def main():
    # Ici on est dans trio, c'est la fête

    conn = TrioConnProxy()
    await conn.init('postgresql:///')

    await conn.execute('CREATE TABLE IF NOT EXISTS users(name text primary key)')

    for name in ('Riri', 'Fifi', 'Loulou'):
        await conn.execute('INSERT INTO users(name) VALUES ($1)', name)

    users = await conn.fetch('SELECT * FROM users')
    print('users:', [user[0] for user in users])


# trio_asyncio s'occupe de configurer l'event loop par défaut de asyncio
# puis lance le <code>trio.run</code> classique trio_asyncio.run(main)</pre>
<p>En plus de ça trio vient avec son module pytest (avec gestion des fixtures asynchrones s&#8217;il vous plait) et Keneith Reitz a promis que la prochain version de requests supporterait async/await et <a href="https://gist.github.com/kennethreitz/fab0f200f47cfa7926607043aed2b483">trio nativement</a>, elle est pas belle la vie !</p>


feed_id: http://sametmax.com/?p=24711
title: Python 3.7 sort de sa coquille 20
uri: Python-3-7-sort-de-sa-coquille-11-Recently-updated
url: http://sametmax.com/python-3-7-sort-de-sa-coquille/
content:
<p>La 3.4 était la première version 3 à valoir le coup, et a donc été le déclencheur de la migration 2->3 qui trainait depuis si longtemps.</p>
<p>La 3.5(.3) a rendu <code>asyncio</code> utilisable, incluant <code>async</code> / <code>await</code> et corrigeant <a href="https://github.com/aio-libs/aiojobs/issues/14">le bug abusé de get_event_loop()</a>.</p>
<p>La 3.6 est mon chouchou. <a href="https://www.python.org/dev/peps/pep-0519/">Sa meilleure intégration de Pathlib</a> et les <a href="https://www.python.org/dev/peps/pep-0498/?">f-strings</a> en font un plaisir total à utiliser. En plus <a href="http://sametmax.com/once-you-go-black-you-never-go-back/">black</a> ne tourne que dessus. Je suis autant que possible en 3.6, je l&#8217;ai même installée sur une vieille centos 7 chez un client.</p>
<p>Alors que vaut cette 3.7, et est-ce qu&#8217;il faut migrer ?</p>
<p>Et bien avec des améliorations de perfs partout et une syntaxe simplifiée pour les classes, c&#8217;est une belle release. La 3.6 va être bien plus facile à avoir sous linux pendant un bon bout de temps et suffit amplement, donc je ne vais pas forcer le pas. Mais bon je l&#8217;ai quand même compilée par acquis de conscience. </p>
<p>Regardons ce qu&#8217;il y a au menu.</p>
<h2>Les data classes</h2>
<p>Clairement la feature phare de la release, les data classes sont une manière plus concise d&#8217;écrire des classes, s&#8217;inspirant de la bibliothèque <a href="http://www.attrs.org/en/stable/">attrs</a> dont elles n&#8217;implémentent qu&#8217;un sous-ensemble.</p>
<p>Une très bonne nouvelle, car je n&#8217;installais jamais attrs: dépendre d&#8217;une lib juste pour ça, m&#8217;embêtait et pour la sérialisation/validation j&#8217;utilise <a href="https://marshmallow.readthedocs.io/en/latest/">marshmallow</a>.</p>
<p>Par exemple:</p>
<pre lang="python">from dataclasses import dataclass

@dataclass
class Achat:
    produit: str
    prix: float
    quantite: int = 0
</pre>
<p>Ce qui va générer une classe toute ce qui a de plus normale, mais dont le <code>__init__</code>, <code>__repr__</code> et <code>__eq__</code> sont automatiquement créés. Vous pouvez bien entendu ajouter les méthodes que vous voulez, comme d&#8217;habitude.</p>
<p>Il ne reste plus qu&#8217;à faire:</p>
<pre lang="python">
>>> print(Achat("foo", 2))
Achat(produit='foo', prix=2, quantite=0)</pre>
<p>Toute la magie est sélectivement désactivable, et une méthode <code>__post_init__</code> est ajoutée à la classe qui fait exactement ce que vous pensez que ça fait.</p>
<p>En prime, on a aussi <code>dataclasses.field</code> qui permet de fournir une factory pour un paramètre (typiquement <code>list</code>, <code>tuple</code>, <code>dict</code>&#8230;).</p>
<p>Puis, comme un bonheur ne vient jamais seul:</p>
<pre lang="python">
>>> from dataclasses import asdict, astuple
>>> print(asdict(Achat("foo", 2)))
{'produit': 'foo', 'prix': 2, 'quantite': 0}
>>> print(astuple(Achat("foo", 2)))
('foo', 2, 0)
</pre>
<p>C&#8217;est récursif sur les dicts, lists, tuples et dataclasses \o/</p>
<p>Enfin, pour finir:</p>
<pre lang="python">>>> from dataclasses import replace
>>> a = Achat("foo", 2)
>>> b = replace(a, quantite=3, prix=1)
>>> print(a, id(a))
Achat(produit='foo', prix=2, quantite=0) 140275795603296
>>> print(b, id(b))
Achat(produit='foo', prix=1, quantite=3) 140275775561456</pre>
<p>Ouai ça déchire.</p>
<p>P.S: <a href="https://pypi.org/project/dataclasses/">y un backport pour la 3.6</a></p>
<h2>asyncio++</h2>
<p>Much love to asyncio dans cette version.</p>
<p>Déjà, un truc qui aurait dû être là dès le début, la nouvelle fonction asyncio.run(), qui masque le setup de l&#8217;event loop pour vous.</p>
<p>On passe de :</p>
<pre lang="python">
loop = asyncio.get_event_loop() 
loop.run_until_complete(coro)</pre>
<p>à:</p>
<pre lang="python">asyncio.run(coro)</pre>
<p>Juste ça, ça fait vachement moins peur aux gens. Et en prime ça évite qu&#8217;ils commencent à chercher la merde avec un setup custom de loop.</p>
<p><code>asyncio.current_task()</code> retourne la tâche dans laquelle on est. D&#8217;ailleurs, un détail, mais on a maintenant l&#8217;équivalent de thread local, <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep567">mais pour la coroutine en cours</a>.</p>
<p><code>asyncio.get_running_loop()</code> retourne la boucle courante, mais seulement si elle existe. Elle lève une exception plutôt que de créer une loop comme <code>get_event_loop()</code> si aucune loop n&#8217;est présente.</p>
<p><code>StreamWriter.wait_closed()</code> permet d&#8217;attendre qu&#8217;un stream se ferme. Les gars de <code>aiohttp</code> doivent être contents.</p>
<p><code>Task.get_loop()</code> retourne la boucle de la tâche. Pour le multi-threading avec plusieurs loops, c&#8217;est cool.</p>
<p><code>loop.create_server()</code> a maintenant un argument <code>start_serving</code> qui contrôle si on veut le lancer immédiatement. J&#8217;ai toujours du mal à croire que des dev qui sont capables de participer à la stdlib ont pu commiter un code qui instancie et enchaine sur un effet de bord. Heureusement c&#8217;est corrigé.</p>
<p>Les handlers retournés par <code>loop.call_later()</code> retournent leur ETA avec <code>.when()</code> et ont une méthode <code>.cancelled()</code>.</p>
<p><a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">Les intensions</a> acceptent maintenant <code>async/await</code>.</p>
<p>Et enfin, les exceptions des tâches annulées ne sont plus loggées. Parce que forcément quand on crashait tout, le log devenait un peu chargé&#8230;</p>
<p>Bon, asyncio était déjà très utilisable en 3.6, n&#8217;exagérons pas. L&#8217;important étant d&#8217;utiliser le mode debug, <code>gather()</code> et <code>run_until_complete()</code>, ce qui devrait être écrit en gros, en rouge dans la doc.</p>
<p>Mais toutes ces modifications sont bienvenues.</p>
<p>Ah, oui, les perfs ont été aussi améliorées&#8230; Mais c&#8217;est le cas partout.</p>
<h2>Des perfs</h2>
<p>Le focus sur les perfs de Python augmente doucement. La 3.6 avait amorcé la tendance, et <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-perf">ça se confirme</a>. J&#8217;attends d&#8217;avoir des retours sur des mises en prod un peu serieuses pour savoir si ça a payé.</p>
<p>Le temps de démarrage de Python est d&#8217;ailleurs pas mal pointé du doigt. Certes, on est pas au niveau de loutre sclérosée que constitue nodejs au réveil, mais c&#8217;est pas une référence. Donc, des choses sont mises en place. Notamment <code>python -X importtime</code> qui <a href="https://docs.python.org/3.7/using/cmdline.html#envvar-PYTHONPROFILEIMPORTTIME">va afficher le temps que prend chaque import</a>.</p>
<p>Des aménagements ont aussi <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep560">été faits</a> pour accélérer le module <code>typing</code>, maintenant que l&#8217;usage des type hints pour les annotations est entériné. Un side effect sympa est que les classes que vous allez écrire seront plus rapides à instancier, et les méthodes plus rapides à résoudre.</p>
<p>D&#8217;ailleurs, les type hints sont maintenant <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep563">résolus paresseusement</a>, à la fois pour améliorer la vitesse de chargement et pour faciliter l&#8217;auto-référencement. </p>
<h2>breakpoint()</h2>
<p><a href="https://www.python.org/dev/peps/pep-0553/">breakpoint()</a> est techniquement un alias configurable à <code>import pdb; pdb.set_trace()</code>. Ça a l&#8217;air de rien, mais c&#8217;est super:</p>
<ul>
<li>C&#8217;est dans les builtins, donc plus facile à découvrir. Les débutants utilisent très peu <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> alors que c&#8217;est un outil formidable.</li>
<li>Plein de gens oublient cette incantation mystique ou font des fautes de frappe.</li>
<li>C&#8217;est facile à spotter dans le code, on peut l&#8217;highlither différement.</li>
<li>C&#8217;est uniforme. Si on veut utiliser un autre débuggeur, on le plug. Mais on utilise toujours la même fonction. On peut même désactiver cette fonction pour éviter de balancer un break point en prod.</li>
<li>C&#8217;est clair. Les débutants n&#8217;ont aucun mal avec <code>debugger</code> en JS parce que c&#8217;est simple de comprendre ce que ça fait au premier coup d&#8217;oeil.</li>
</ul>
<p>Ça vient, bien entendu avec une variable d&#8217;environnement et d&#8217;un hook dans <code>sys</code> pour custo le comportement.</p>
<h2>Quelques détails</h2>
<h3>Dicts ordonnés</h3>
<p>La spec garantit que les clés vont garder leur ordre d&#8217;insertion. C&#8217;était déjà le cas en 3.6, la 3.7 rend juste la mesure officielle.</p>
<p>Ne jetez pas OrderedDict à la poubelle pour autant, car il préserve l&#8217;ordre des clés après suppression également.</p>
<h3>async/await sont des mots clés</h3>
<p>Et ne peuvent donc plus être écrasés par erreur. C&#8217;est juste l&#8217;application de l&#8217;annonce faite à l&#8217;introduction de ces mots clés.</p>
<h3>Des sœurs pour __getitem__ et __getattr__</h3>
<p>On va pouvoir définir un <code>__getattr__</code> sur les modules (surtout utile pour le lazy loading) et un <code>__class_getitem__</code> pour pouvoir faire <code>MaClass[]</code> sans utiliser de metaclass.</p>
<h3>Traduction de la doc</h3>
<p>Le processus pour avoir des docs dans d&#8217;autres langues est maintenant officiel. Pour l&#8217;instant <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep545">le jap, le koréen et le kokorico</a></p>
<h3>DeprecationWarning plus visibles</h2>
<p>La connerie de les cacher <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep565">a été corrigée</a>. Qui a pensé que c&#8217;était une bonne idée ? Mais seulement pour le script principal, ce qui va permettre aux dev des libs de les voir sans faire chier les utilisateurs.</p>
<h3>Debug mode</h3>
<p><code>python -X dev</code> va devenir votre nouvel ami, <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-devmode">activant</a> tout un tas de fonctions de debug coûteuses en production. Notamment plus de warning, asyncio debug mode, le faulthandler qui dump la stacktrace en cas de catastrophe, etc.</p>
<h3>Des pyc reproductibles</h3>
<p>Un même fichier <a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep552">donnera maintenant toujours</a> un même .pyc. C&#8217;est pour les packagers et les amateurs de sécu.</p>
<h3>Meilleur ImportError</h3>
<p>L&#8217;exception <a href="https://docs.python.org/3.7/whatsnew/3.7.html#importlib-resources">va maintenant</a> afficher le nom du module et son <code>__file__</code> path si <code>from ... import</code> broute. Ça va rendre les imports circulaires, la plaie des gros projets Python, plus faciles à debugger.</p>
<h3>packaging</h3>
<p>Introduction de importlib.resources, <a href="https://docs.python.org/3.7/library/importlib.html#module-importlib.resources">un remplacement</a> pour le détestable <code>pkg_resource</code> qui va rendre sans regret <a href="http://sametmax.com/embarquer-un-fichier-non-python-proprement/">mon article</a> obsolète.</p>
<p>Autre ajout notable: <code>README.rst</code> est maintenant reconnu et ajouté automatiquement quand on fait son paquet cadeau. Puisque maintenant pypi accepte le markdown, ça aurait été cool de le faire avec les <code>.md</code> également.</p>
<h3>time est plus précis</h3>
<p><a href="https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep564">Sensible à la nanoseconde</a>. Perso je m&#8217;en bats les steaks mais je me suis dit que je ferai passer l&#8217;info.</p>
<h3>unittest -k</h3>
<p><a href="https://docs.pytest.org/en/latest/usage.html">Copieurs.</a></p>
<h3>namedtuple supporte les valeurs par defaut</h3>
<p>Rien à ajouter, si ce n&#8217;est qu&#8217;entre SimpleNamespace et les dataclasses, je crois qu&#8217;on a de quoi voir venir. Même si j&#8217;aimerais avoir un literal pour les namedtuples sous la forme de <code>(foo=1, bar=2)</code> mais ça a été refusé.</p>
<h3>Ajouts à Contexlib</h3>
<p>Quelques <a href="https://docs.python.org/3.7/whatsnew/3.7.html#contextlib">outils en plus</a>, dont un context manager qui ne fait rien (rigolez pas, c&#8217;est super utile !), et des contexts managers async.</p>
<h3>lifting pour subprocess</h3>
<p>Ok, plutôt bottox. <a href="https://docs.python.org/3.7/whatsnew/3.7.html#subprocess">C&#8217;est cosmétique</a>, mais c&#8217;est bienvenu: des aménagements pour rendre les appels un poil plus courts, notamment dans le cas de la capture des stdx.</p>
<p>&#8230;<br />
&#8230;<br />
&#8230;</p>
<p>Et encore plein <a href="https://docs.python.org/3.7/whatsnew/3.7.html#">d&#8217;autres mini trucs</a>.</p>
<p>C&#8217;est dispo en DL pour <a href="https://www.python.org/downloads/release/python-370/">windows et mac</a>. Pour linux, comme d&#8217;hab, soit on attend la mise à jour des depôts/ppa/etc, soit on compile à la main (étonnamment facile, si on se rappelle de faire <code>make altinstall</code> et pas <code>make install</code>), soit on utilise l&#8217;excellent pyenv et <code>pyenv install 3.7</code>.</p>


feed_id: http://sametmax.com/?p=24750
title: Le don du mois: mobx 7
uri: Le-don-du-mois-mobx-6-Recently-updated
url: http://sametmax.com/le-don-du-mois-mobx/
content:
<p>Si vous avez suivi un peu les différents <a href="http://sametmax.com/tag/don/">dons du mois</a> au fur et à mesure de la vie du blog, vous avez du vous rendre compte de 2 choses:</p>
<ul>
<li>Le don du mois n&#8217;est pas mensuel. Il est juste limité à un par mois. Ça m&#8217;évite la pression d&#8217;être un bon samaritain. Sauf que du coup, j&#8217;oublie parfois pendant trèèèèèèès longtemps :)</li>
<li>Il n&#8217;y a pas beaucoup de projets JS dans le lot. Ahem.</li>
</ul>
<p>En fait le seul et unique projet JS supporté a été <a href="http://sametmax.com/le-don-du-mois-vue-js/">VueJS</a>. C&#8217;est dire que la barre est haute, étant donné la qualité exceptionnelle de ce projet.</p>
<p>Donc quand je vous dis que j&#8217;ai donné 50 balles à <a href="https://github.com/mobxjs/mobx">Mobx</a>, c&#8217;est que le projet déchire. Et il déchire <strong>malgré</strong> le fait qu&#8217;il soit codé en JS.</p>
<p>Mobx permet, en gros, de surveiller les modifications à une structure de données. Vous posez un marqueur sur la structure, et un sur les fonctions utilisant la structure, et c&#8217;est tout:</p>
<pre lang="javascript">class TodoList {
    @observable todos = []; // dire à mobx de surveiller
}

...

@observer // dire à mobx de tenir à jour
class TodoListView extends Component {
    render() {
        return <ul>
            {this.props.todoList.todos.map(todo =>)}
        </ul>
    }

</pre>
<p> C&#8217;est là la brillance du système: malgré sa simplicité, mobx va récursivement réagir à toute modifications, même sur des données complexes imbriquées; Et calculer toutes les dépendances de chaque fonction pour ne les appeler qu&#8217;au meilleur moment.</p>
<p>C&#8217;est facile à utiliser, et étonnamment rapide à exécuter.</p>
<p>Le résultat ? Quand un client me force à utiliser ReactJS, je saute redux, et je met Mobx à la place. Ca donne <em>presque</em> l&#8217;impression d&#8217;utiliser Vue: le code de manipulation d&#8217;état est simple à comprendre, gentil sur le CPU et les mutations d&#8217;état restent courtes et élégantes. Le reste est toujours moche, mais ça on y peut rien.</p>
<p>Bref, mobx est ce qui rend react acceptable. Et tout ce qui peut apaiser la douleur du dev en front-end n&#8217;a pas de prix.</p>
<p>J&#8217;ai regardé le code source, et la popote interne est bien complexe. Mais à chaque fois que je veux l&#8217;utiliser je me dis que ça ne pourra pas être si simple&#8230; et si.</p>
<p>La page de don, <a href="https://mobx.js.org/donate.html">c&#8217;est par là</a>.</p>


feed_id: http://sametmax.com/?p=24766
title: L’expression d’assignation vient d’être acceptée 20
uri: L-expression-d-assignation-vient-d-être-acceptée-12-Recentl
url: http://sametmax.com/lexpression-dassignation-vient-detre-acceptee/
content:
<p>Après des mois de débats sur <a href="https://mail.python.org/mailman/listinfo/python-ideas">python-idea</a> (mailing list sur laquelle, je vous le rappelle, tout le monde a le droit de participer), Guido <a href="https://groups.google.com/forum/#!topic/dev-python/egS7A22oJgE%5B151-175%5D">a validé</a> la <a href="https://www.python.org/dev/peps/pep-0572/">PEP 572</a>. <code>(foo := bar)</code> sera donc un code valide en Python 3.8.</p>
<p>Je n&#8217;avais pas vu de feature plus controversée depuis les <a href="http://sametmax.com/le-formatage-des-strings-en-long-et-en-large/">f-strings</a>. Et je gage que, comme les f-strings, après un temps d&#8217;adaptation, la communauté va se demander comment on a vécu sans auparavant.</p>
<h2>Un peu d&#8217;histoire</h2>
<p>Il existe deux grandes catégories d&#8217;instructions dans les langages de programmation. Les déclarations et les expressions.</p>
<p>La déclaration, en anglais &#8220;statement&#8221;, est une action indépendante formulée sur une ligne. C&#8217;est une unité syntaxique, et une déclaration ne peut être contenue dans une autre déclaration sur la même ligne.</p>
<p>Ex:</p>
<pre lang="python">
import os
</pre>
<p>est une déclaration. Un import est tout seul sur sa ligne et ne se combine pas avec d&#8217;autres instructions.</p>
<p>L&#8217;expression, elle, est une combinaison de littéraux, variables, d&#8217;opérateurs et d&#8217;appels de fonctions qui retournent un résultat. Les expressions peuvent contenir d&#8217;autres expressions, et elles peuvent être contenues dans une déclaration.</p>
<p>Ex:</p>
<pre lang="python">1 + 1 </pre>
<p>est une expression. On peut, en effet, assigner le résultat de ce code à une variable, le passer à une fonction en paramètre ou le tester dans une condition.</p>
<p>Les langages, comme le COBOL, qui privilégient le style impératif utilisent majoritairement des déclarations. Les langages, comme LISP, qui privilégient le style fonctionnel, utilisent majoritairement des expressions.</p>
<p>Très souvent néanmoins, les langages populaires font largement usage des deux. L&#8217;expression est plus flexible et plus puissante. La déclaration force une opinion sur la structure du programme et évite les divergences de style. Selon la philosophie que l&#8217;on souhaite donner à son bébé, un créateur de langage va donc s&#8217;orienter plus vers l&#8217;une ou l&#8217;autre.</p>
<p>Python est multiparadigme et soutient le style impératif, fonctionnel et orienté objet. Il possède donc non seulement des expressions et des déclarations, mais également souvent les deux versions pour une même instruction.</p>
<p>Ex, les déclarations:</p>
<pre lang="python">squares = []
for x in numbers:
    squares.append(x * x)

def mean(x):
    return x * x / 2

if is_ok:
    print(welcome)
else:
    print(error)</pre>
<p>ont des expressions équivalentes:</p>
<pre lang="python">

squares = [x * x for x in number]

mean = lambda x: x * x / 2

print(welcome if is_ok else error)
</pre>
<p>Parfois Python choisit d&#8217;orienter le style du programmeur, non pas évitant de fournir des expressions, mais par le biais de la grammaire imposée. Ainsi il oblige à indenter, et n&#8217;autorise pas les lambdas à contenir de déclaration. C&#8217;est une autre stratégie pour imposer une philosophie au langage. Pour Python, la philosophie est que la capacité à s&#8217;exprimer doit rester riche, mais pas au détriment de la capacité à comprendre le code.</p>
<p>Une particularité de Python, c&#8217;est que l&#8217;assignation, c&#8217;est-à-dire le fait d&#8217;associer une valeur à une variable, est une déclaration. Ex:</p>
<pre lang="python">a = 1</pre>
<p>Comme les déclarations ne peuvent contenir d&#8217;autres déclarations, cette syntaxe interdit:</p>
<pre lang="python">if a = 1:  </pre>
<p>Ce n&#8217;est pas le cas dans de nombreux langages populaires, comme le C, PHP, le JS&#8230; Exemple en Ruby:</p>
<pre lang="ruby">if (value = Settings.get('test_setting'))
  perform_action(value)
end</pre>
<p>Ici, non seulement on assigne le résultat du <code>get()</code> à la variable <code>value</code>, mais en plus, on teste le résultat du <code>get()</code> avec le <code>if</code>.</p>
<p>Actuellement ceci est impossible en Python, et le même code serait:</p>
<pre lang="python">value = Settings.get('test_setting')
if value:
  perform_action(value)</pre>
<p>Ce n&#8217;est pas une erreur, c&#8217;est un choix de design. En effet une source de bug très courante en programmation est de vouloir faire une comparaison, mais de taper une assignation.</p>
<p>Ainsi, quelqu&#8217;un voudrait faire:</p>
<pre lang="python">while reponse == "oui":
    ...
    reponse = input('Voulez-vous continuer ?')</pre>
<p>Mais ferait:</p>
<pre lang="python">while reponse = "oui": # erreur subtile et difficile à voir
    ...
    reponse = input('Voulez-vous continuer ?')</pre>
<p>Ce qui ne compare pas DU TOUT la variable. Et en plus change son contenu. Dans ce cas précis, le résultat est une boucle infinie, mais parfaitement valide et qui ne provoquera pas d&#8217;erreur.</p>
<p>Pour éviter ce genre de bug que même les programmeurs aguerris font un jour de fatigue, la syntaxe a tout simplement été interdite en stipulant que l&#8217;assignation était toujours une déclaration.</p>
<h2>La PEP 572</h2>
<p>L&#8217;absence de cette fonctionnalité a eu d&#8217;excellents bénéfices. Je le vois régulièrement dans mes salles de classe, ce bug. La <code>SyntaxError</code> qui résulte de cette faute en Python permet de l&#8217;attraper avant qu&#8217;il ne fasse le moindre dégât.</p>
<p>Car c&#8217;est tout le problème de cette erreur: si la syntaxe est valide, le bug est silencieux, le code tourne, il ne fait juste pas du tout ce qu&#8217;on lui demande. C&#8217;est la plus pernicieuse des situations, avec des conséquences qui peuvent ne se déclarer que bien plus loin dans le code et une séance de débuggage des plus irritantes.</p>
<p>A mon sens, c&#8217;était une excellente décision de design.</p>
<p>Pourtant la PEP 572 revient dessus, en proposant, comme pour <code>lambda</code>, la boucle <code>for</code> ou la condition, un équivalent sous forme d&#8217;expression.</p>
<p>Pourquoi ?</p>
<p>Et bien Python doit aussi satisfaire les programmeurs chevronnés, qui en ont marre de se retrouver avec des situations comme :</p>
<pre lang="python">match1 = pattern1.match(data)
if match1:
    print(match1.group(1))
else:
    match2 = pattern2.match(data)
    if match2:
        print(match2.group(2))</pre>
<p>Certes, ce code est clair et facile à comprendre, mais il est très verbeux. On doit faire avec une indentation artificiellement induite par la limite de la syntaxe, et non par la logique du raisonnement qui est ici parfaitement linéaire.</p>
<p>Comment donc réconcilier le désir d&#8217;éviter le fameux bug tout en satisfaisant les besoins d&#8217;expressivité, légitimes une fois qu&#8217;on quitte le nid des débutants ?</p>
<p>La solution proposée est triple :</p>
<ul>
<li>Ajouter un nouvel opérateur dédié, permettant l&#8217;assignation sous forme d&#8217;expression.</li>
<li>Forcer l&#8217;usage des parenthèses pour encadrer cette expression.</li>
<li>Rendre les deux opérateurs d&#8217;assignation mutuellement exclusifs.</li>
</ul>
<p>Le nouvel opérateur choisi est <code>:=</code> et il ne peut exister qu&#8217;entre parenthèses. Il peut être utilisé là où un simple <code>=</code> ne serait pas autorisé. Mais, il ne peut PAS être utilisé là où on peut utiliser <code>=</code>. Le but est de ne jamais mettre ces deux opérateurs en concurrence: une situation permet l&#8217;un ou l&#8217;autre, jamais les deux.</p>
<p><code>=</code> ne change pas. La seule différence, c&#8217;est qu&#8217;à partir de Python 3.8, vous aurez le droit de faire:</p>
<pre lang="python">
if (match1 := pattern1.match(data)):
    print(match1.group(1))
elif (match2 := pattern2.match(data)):
    print(match2.group(2))</pre>
<p>L&#8217;opérateur <code>:=</code> permet donc bien, dans des situations très précises, d&#8217;obtenir un code plus cours et élégant, sans introduire pourtant d’ambiguïté et donc de bug potentiel. Il autorise une nouvelle forme d&#8217;expressivité, mais sa syntaxe est très marquée: impossible de le confondre avec son frère, et les parenthèses l&#8217;isolent du reste du code.</p>
<p>On ne se pose pas non plus la question de quand choisir <code>=</code> et <code>:=</code> puisque:</p>
<pre lang="python">a = 1</pre>
<p>est valide, mais pas:</p>
<pre lang="python">a := 1</pre>
<p>Bien que:</p>
<pre lang="python">(a := 1)</pre>
<p>soit valide, personne n&#8217;aura envie d&#8217;utiliser vainement cette forme plus lourde.</p>
<p>L&#8217;usage de <code>:=</code> est donc marginal, et cantonné à des cas particuliers.</p>
<h2>Une opinion, c&#8217;est comme un trou du cul&#8230;</h2>
<p>Personnellement j&#8217;étais mitigé sur l&#8217;idée. De plus, j&#8217;aurais préféré l&#8217;usage du mot clé <code>as</code>, puisqu&#8217;on l&#8217;utilisait déjà dans les imports, les context managers et la gestion des exceptions. </p>
<p>Chaque ajout d&#8217;expression rajoute également la possibilité d&#8217;abus. Si vous avez déjà vu ces horreurs à base de lambdas imbriquées ou d&#8217;intensions sans fin, vous savez de quoi je parle.</p>
<p>Avec <code>:=</code>, on peut vraiment se lancer dans du grand n&#8217;importe quoi:</p>
<p>Pour reprendre l&#8217;exemple de la PEP:</p>
<pre lang="python">while True:
    old = total
    total += term
    if old == total:
        return total
    term *= mx2 / (i*(i+1))
    i += 2</pre>
<p>est très clair. </p>
<p>En revanche:</p>
<pre lang="python">while total != (total := total + term):
    term *= mx2 / (i*(i+1))
    i += 2
return total</pre>
<p>Est une abomination qu&#8217;il faut purger par le feu.</p>
<p>Mais par expérience, j&#8217;ai rarement vu en 15 ans de Python beaucoup d&#8217;abus de ses fonctionnalités avancées. Les bénéfices ont toujours dépassé le coût d&#8217;une large marge. Pourtant entre les décorateurs, les dunder methods et les meta classes, il y a matière à messe noire.</p>
<p>Par ailleurs j&#8217;avoue que je suis ravi de pouvoir enfin faire:</p>
<pre lang="python">while (data := io.get(x)):</pre>
<p>Et:</p>
<pre lang="python">[bar(x) for z in stuff if (x := foo(z))]</pre>
<p>La PEP mentionne aussi un exemple que je n&#8217;avais pas prévu, et qui souffle le chaud et le froid:</p>
<pre lang="python">diff = x - x_base
if diff:
    g = gcd(diff, n)
    if g > 1:
        return g</pre>
<p>Peut devenir:</p>
<pre lang="python">if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
    return g
</pre>
<p>Comme l&#8217;auteur, j&#8217;approuve le fait que la première version est inutilement verbeuse, mais contrairement à lui, je trouve que la seconde est bien trop complexe pour être scannée d&#8217;un coup d’œil.</p>
<p>En revanche:</p>
<pre lang="python">diff = x - x_base
if diff and (g := gcd(diff, n)) > 1:
    return g</pre>
<p>est tout à fait à mon goût.</p>
<p>Ceci démontre bien qu&#8217;il va falloir un temps d&#8217;adaptation avant que la communauté trouve l&#8217;équilibre entre Perl et BASIC. Quoi qu&#8217;il en soit, on n’aura pas à s&#8217;en soucier avant l&#8217;année prochaine, et même d&#8217;ici là, peu de code pourra en faire usage avant que la 3.8 soit largement installée.</p>
<p>De mon côté je m&#8217;attends à ce qu&#8217;on ignore majoritairement cette fonctionnalité, jusqu&#8217;au moment où elle apparaîtra dans un coin de l&#8217;esprit le temps d&#8217;un besoin ponctuel et local, pour être oubliée à nouveau jusqu&#8217;à l&#8217;occasion suivante. Comme <del datetime="2018-07-03T09:40:56+00:00">Dieu</del> Guido l&#8217;aura voulu. D&#8217;ailleurs, côté enseignement, je ne compte pas introduire l&#8217;opérateur dans mes cours, ou alors dans une section bonus, à moins qu&#8217;un participant ne pose la question.</p>
<p>Aller, vous pouvez râler en commentaire maintenant :)</p>


feed_id: http://sametmax.com/?p=24844
title: Guido van Rossum s’offre “des vacances permanentes” 19
uri: Guido-van-Rossum-s-offre-des-vacances-permanentes-2
url: http://sametmax.com/guido-van-rossum-soffre-des-vacances-permanentes/
content:
<p>Le <abbr title="Benevolent dictator for life">BDFL</abbr> (Dictateur <del datetime="2018-07-13T07:24:24+00:00">Bénévole</del> Bienveillant À Vie) et créateur du langage Python <a href="https://www.mail-archive.com/python-committers@python.org/msg05628.html">vient d&#8217;annoncer</a> qu&#8217;il laissait son bébé à la communauté.</p>
<p>Sans quitter son rôle de core dev, et en suggérant qu&#8217;il passe plus de temps en tant que mentor de ses collègues sur le projet, il abandonne néanmoins son pouvoir de décision absolu sur le langage et son rôle de validateur ultime de chaque introduction de nouvelles fonctionnalités.</p>
<p>Dans son email, il ne passe pas le pouvoir à qui que ce soit ni n&#8217;invite à un mode de direction particulier. Il suggère que l&#8217;équipe actuelle des core devs, les développeurs ayant les droits de commit sur le repository du langage, choisisse le format qui leur convienne le mieux pour diriger à présent le projet.</p>
<p>Un moment important dans la vie de Python, mais aussi un événement qui demande beaucoup de remise en contexte.</p>
<h2>Python-idea, Python-dev et les PEP</h2>
<p>Durant les dernières années, les décisions de modification du langage passaient généralement par plusieurs phases.</p>
<p>D&#8217;abord, la proposition faite sur la mailing list <a href="https://mail.python.org/mailman/listinfo/python-ideas">python-idea</a>. Cette liste est publique. Tout le monde peut y participer et y donner son avis.</p>
<p>Après débat, si le climat n&#8217;est pas hostile (ce qui est une notion TRES subjective), un des core devs suggère généralement à l&#8217;auteur de l&#8217;idée d&#8217;écrire un PEP.</p>
<p>Le <abbr title="Python Enhancement Proposal">PEP</abbr> (Proposition d&#8217;Amélioration de Python) est l&#8217;équivalent d&#8217;une RFC pour Python. C&#8217;est un document formalisant une proposition d&#8217;amélioration du langage et de son écosystème. Le plus connu est bien entendu le <a href="https://www.python.org/dev/peps/pep-0008/">PEP 8</a>.</p>
<p>S&#8217;ensuit encore plus de débats, et des modifications itératives du PEP, jusqu&#8217;à, soit l&#8217;abandon du projet par l&#8217;auteur, soit l&#8217;oubli, soit le verdict de Guido.</p>
<p>Ce dernier est définitif: le PEP est approuvé ou rejeté. Dans le premier cas, il sera appliqué. Dans le second, il part à la poubelle.</p>
<p>Quelque part à la fin de ce processus, les implémenteurs du PEP discutent en plus petit comité, sur la liste python-dev, de la réalisation.</p>
<p>Guido a toujours, jusqu&#8217;ici, été donc la dernière étape de filtre de cet enchaînement. A la foi gardien de sa philosophie du langage, et goulot d&#8217;étranglement.</p>
<p>Il y a eu quelques améliorations, comme la nomination ponctuelle de BDFL délégués pour certains sujets, mais le format reste quand même globalement le même.</p>
<h2>Pride and prejudice</h2>
<p>Ce système a l&#8217;avantage d&#8217;être très ouvert. Tout le monde peut participer. Peu de personnes le font pourtant, par rapport à la masse d&#8217;utilisateurs de Python, mais c&#8217;est déjà beaucoup si on considère l&#8217;inertie que ça implique.</p>
<p>Le mail est un format très accessible, décentralisé, ouvert et standard. Son austérité évite l&#8217;effet réseau social qu&#8217;on voit trop souvent sur les outils plus modernes.</p>
<p>En contrepartie, le processus est très flou. Il n&#8217;y a pas de vote a proprement parler. Les threads s&#8217;enchaînent un peu n&#8217;importe comment. Les nouveaux venus ne sachant pas comment utiliser l&#8217;outil le font imparfaitement. Et le media ne permet pas facilement de suivre la continuité à court terme et à long terme de grand-chose, ni en termes de flux, ni en termes de référence, ni en termes de recherche.</p>
<p>Mais c&#8217;est aussi l&#8217;aspect social qui est problématique. Il n&#8217;y a aucune organisation claire dans la liste, et tout le monde semble &#8220;au même niveau&#8221;. Or ce n&#8217;est pas absolument pas le cas. La réputation et les participations passées, ainsi que les caractères des participants et leurs relations jouent énormément sur le processus. Le timing également.</p>
<p>Ça parait équitable sur le papier, mais c&#8217;est une illusion, et en prime cela implique des frictions qui pourraient être évitées. Par exemple quand un étudiant demande à Larry Hastings de l&#8217;aider à faire ses devoirs ou qu&#8217;un auteur de PEP cite le Zen of Python à Tim Peters. Inversement, quand vous proposez une idée, et que tout le monde vous envoie péter, mais que 6 mois plus tard, Brett Cannon dit que c&#8217;est intéressant et que tout le monde crie au génie, ça fout les boules.</p>
<p>Ajouté à cela, la qualité du débat qui peut varier du tout au tout : du caprice à la revue technique, en passant par le mail à côté de la plaque, la crise d&#8217;égo, l&#8217;appel au calme, le récap qui aide tout le monde, les idées brillantes, les suggestions étonnantes, les redites, et le spam.</p>
<p>Et évidement, <a href="https://rework.fm/say-no/">la réponse par défaut est toujours non.</a></p>
<p>Se faire entendre là dedans est très difficile. Garder son calme l&#8217;est souvent aussi. Mais surtout, persévérer à travers le processus durant le temps nécessaire pour l&#8217;aboutissement de celui-ci est une épreuve épuisante, irritante, et ingrate. Surtout quand 9 fois sur 10, elle se finit par un rejet.</p>
<p>Un rejet cependant, n&#8217;est pas la mise à mort d&#8217;une idée. L&#8217;année suivante on peut relancer le débat, et ainsi de suite, comme un politicien à l&#8217;assemblée qui veut faire passer son projet de loi. Et comme au Parlement, la même idée présentée par une nouvelle personne, ou avec un autre timing peut avoir un résultat radicalement différent.</p>
<h2>Un anus pour les rassembler tôt</h2>
<p>GvR, bien qu&#8217;au sommet de cette pyramide, n&#8217;est pas isolé de tout cela, bien au contraire. Il est une des rares personnes qui doit trancher sur presque tout, et donc se coltiner une bonne partie des débats. Et des réactions quand il rejette l&#8217;idée d’autrui.</p>
<p>À ceci se rajoute sa présence sur les bugs trackers, et bien entendu son activité de développeur.</p>
<p>Un rôle difficile, fatigant, et un vrai sacerdoce pour quelqu&#8217;un qui pourrait dire &#8220;allez tous vous faire foutre, j&#8217;ai pondu ce langage utilisé par des millions de personnes tout seul, je sais mieux que vous&#8221; au lieu de prendre en considération l&#8217;avis du public.</p>
<p>Un rôle, je vous le rappelle, qu&#8217;il tient depuis plus de 20 ans.</p>
<p>Depuis la 3.4, on sent le poids commencer à peser sur ses épaules. A 62 ans, et toujours avec un travail à plein temps chez Dropbox (qui heureusement lui laisse le loisir de travailler sur Python), on peut imaginer l&#8217;énergie nécessaire pour s&#8217;impliquer encore autant.</p>
<p>Cela se ressent particulièrement dans ses mails et ses tickets. Une sorte de lassitude. Et une retenue qu&#8217;on devine de plus en plus difficile.</p>
<p>Honnêtement, je ne sais pas comment il a fait pour ne pas exploser sur quelqu&#8217;un. Dans certains échanges que j&#8217;ai eus avec lui sur la liste ou sur github, si nos rôles avaient été inversés, j&#8217;aurais sans aucun doute été bien moins diplomate.</p>
<p><code>sys.exit()</code> maintenant, avant que la charge ne devienne trop pesante, est à mon sens un acte de grande classe.</p>
<p>Comme un comédien, un musicien, un metteur en scène ou un écrivain qui fait ses adieux au sommet de son art. J&#8217;aurais aimé que Lucas, Spielberg et Besson aient su en faire autant.</p>
<p>Mais pour bien comprendre à quel point cette décision de laisser sa place demande du courage, il faut réaliser une chose: il laisse son enfant dans les mains des autres. L’œuvre de sa vie. Une réalisation colossale qui plus est, qui a généré des centaines de milliers d&#8217;emplois, fait tourner des milliers de projets.</p>
<p>Moi, j&#8217;ai du mal à m&#8217;imaginer arrêter d&#8217;écrire ce misérable petit blog. Et pourtant j&#8217;y ai pensé souvent.</p>
<p>L&#8217;étincelle qui a fait déborder la moutarde, c&#8217;est bien entendu le débat sans fin sur <a href="http://sametmax.com/lexpression-dassignation-vient-detre-acceptee/">l&#8217;expression d&#8217;assignation</a>, et la critique vigoureuse de son acceptation. (C&#8217;est vrai que <a href="https://lwn.net/Articles/757713/">c&#8217;était chaud</a>)</p>
<p>Guido en a eu ras le cul, quoi.</p>
<h2>So what now ?</h2>
<p>Personnellement, j&#8217;accueille la nouvelle avec un mélange d&#8217;espoir et de mélancolie.</p>
<p>Python n&#8217;aurait jamais été ce qu&#8217;il est aujourd&#8217;hui sans la constante vigilance de son BDFL.</p>
<p>Dire &#8220;non&#8221; est la partie la plus importante pour sculpter une expérience. C&#8217;est ce qui fait la différence entre Gates et Jobs, Van dam et Lee, Hitler et&#8230; heu&#8230; non.</p>
<p>C&#8217;est ce qui fait qu&#8217;on n&#8217;a des <code>lambda</code> bridées et pas d&#8217;opérateur pour ajouter un élément dans une liste. Qu&#8217;on le veuille ou pas.</p>
<p>Et c&#8217;est ce qui fait qu&#8217;un langage né en fucking 1985 (avant Java !) tient toujours la route aujourd&#8217;hui. A gardé sa lisibilité. Sa facilité de prise en main. Et continue d&#8217;être utile.</p>
<p>C&#8217;est un travail de titan !</p>
<p>Néanmoins je ne peux m&#8217;empêcher de noter que les dernières fonctionnalités majeures de Python ont été introduites de manière brouillonne. Je pense notamment au type hints et à asyncio, que Guido a <code>bdfl -f</code> sans donner le temps de mûrir leur design. Elles ont mis plusieurs versions à ne serait-ce qu&#8217;être utilisables, et méritent encore du travail.</p>
<p>Je pense aussi que Python est prêt pour des ajustements, et espère que passer le flambeau à l&#8217;équipe de core dev va apporter du renouveau au langage.</p>
<p>En effet, il est peu probable qu&#8217;un nouveau BDFL s&#8217;installe, et bien qu&#8217;il soit trop tôt pour faire une prédiction, la mise en place d&#8217;un quorum semble plus probable. Dans ce cas, il faudra sans doute un vecteur de vote. Et de là, qui sait, naîtra peut-être un complément ou replacement à python-idea.</p>
<p>Je l&#8217;espère en tout cas.</p>
<p>Sortir de l&#8217;usage de la mailing list pour un outil plus encadré, mettant les propositions en avant, avec un système de sondage, des procédures plus claires, des références plus faciles au passé, et une distinction explicite du statut des personnes qui s&#8217;expriment.</p>
<p>Bref, faciliter l&#8217;accès au processus, tout en permettant une gestion plus saine. On ne voudrait pas que Victor ou Yuri nous posent leur dem dans les 6 mois pour cause de pétage-de-cablite aigue.</p>
<p>Également, qui sait, peut-être reviendra-t-on &#8211; pour le meilleur ou pour le pire ? &#8211; sur des BanDFL tel que:</p>
<ul>
<li>le pattern matching</li>
<li>les exceptions sous forme d&#8217;expression</li>
<li>pathlib.Path dans les builtins</li>
<li>le mot clé <code>lazy</code></li>
<li>et bien d&#8217;autres</li>
</ul>
<p>Difficile de croire que le débat ne sera pas relancé maintenant que Cerbère ne garde plus les Champs Élysées.</p>
<p>Évidemment, il est logique qu&#8217;il y ait un temps de flottement. D&#8217;abord par respect pour le père de Python. Ça ferait un peu GoT d’enchaîner quand même. Ensuite parce qu&#8217;il va falloir qu&#8217;un nouveau mode de fonctionnement émerge, et prouve son efficacité.</p>
<h2>Quoi qu&#8217;il arrive</h2>
<p>Merci à Guido Van Rossum pour ce cadeau immense.</p>
<p>On va essayer de ne pas trop l’abîmer.</p>


feed_id: http://sametmax.com/?p=24891
title: La débâcle de async en 3.7
uri: La-débâcle-de-async-en-3-7-5-Recently-updated
url: http://sametmax.com/la-debacle-de-async-en-3-7/
content:
<p>Quand les nouveaux mots clés <code>async</code> et <code>await</code> ont été introduits en Python 3.5, tout le monde a trouvé l&#8217;idée formidable. D&#8217;ailleurs, ça a été intégré à JavaScript.</p>
<p>Malheureusement, introduire des mots clés dans un langage est une opération très délicate.</p>
<h2>Limites et contournements des mots clés</h2>
<p>En Python les mots clés ont une caractéristique importante : on ne peut pas les utiliser pour quoi que ce soit d&#8217;autre.</p>
<p>Par exemple, <code>class</code> est un mot clé, donc je ne peux pas créer une variable, un attribut, ou une fonction appelé <code>class</code>. Ceci lève une  erreur:</p>
<pre lang="python">>>> class = 1
  File "<stdin>", line 1
    class = 1
          ^
SyntaxError: invalid syntax
>>> class Foo: pass
... 
>>> Foo.class = 1
  File "<stdin>", line 1
    Foo.class = 1
            ^
SyntaxError: invalid syntax
>>> </pre>
<p>Pour cette raison, quand on veut qu&#8217;une variable contienne une classe en Python, on la nomme <code>cls</code>:</p>
<pre lang="python">>>> class Bar:
...     @classmethod
...     def wololo(cls):
...         print(cls, 'wololo')
... 
>>> 
>>> Bar.wololo()
<class '__main__.Bar'> wololo
>>> </pre>
<p>C&#8217;est aussi pour cela que vous voyez parfois des variables nommées <code>truc_</code>. Souvent <code>from_</code> par exemple, parce que <code>from</code> est un mot clé.</p>
<p>(pro tip: plutôt que <code>from</code> et <code>to</code>, utilisez <code>src</code> et <code>dest</code>)</p>
<p>Quand en Python 2 on a introduit <code>True</code> et <code>False</code>, un gros problème s&#8217;ensuivit: soit on en faisait des mots clés, et on pétait tout le code précédent qui utilisait ces mots, soit on en faisait des variables globales.</p>
<p>Le choix a été de garder la stabilité jusqu&#8217;à la prochaine version majeure, et c&#8217;est pour cela que:</p>
<ul>
<li>On peut faire <code>True = False</code> en Python 2. Ouch.</li>
<li>Python 3 casse ce comportement, et donc ça fait une chose de plus à laquelle il faut penser quand on migre.</li>
</ul>
<p>Pour la 3.5, on avait donc ce même problème, avec une cerise sur le gâteau: la lib standard utilisait elle-même la fonction <code>asyncio.async</code>.</p>
<p>Le choix a donc de faire de <code>async</code> / <code>await</code> des variables globales, et de les transformer en mot clé en 3.7.</p>
<p>En 3.6, un warning a été ajouté pour rappeler aux gens de migrer leur code.</p>
<p>C&#8217;est un sacré taf, et ça comporte des risques comme nous allons le voir plus loin. C&#8217;est pour cette raison que l&#8217;ajout d&#8217;un mot clé dans Python est une des choses les plus difficiles à faire passer sur la mailling list python-idea.</p>
<h2>Arrive la 3.7</h2>
<p>La 3.7 est sortie avec <a href="http://sametmax.com/python-3-7-sort-de-sa-coquille/">tout un tas de goodies</a>. Youpi. Mais aussi avec le passage de <code>async/await</code> de variables globales à mots clés, cassant la compatibilité ascendante. Quelque chose de rare en Python, et que personnellement j&#8217;aurais réservé pour Python 4, ne serait-ce que pour respecter semver.</p>
<p>Le résultat, tout un tas de systèmes ont pété: des linux en rolling release, des gens qui ont fait l&#8217;update de Python à la main, des gens qui maintiennent des libs compatibles 3.5 a 3.7&#8230;</p>
<p>D&#8217;autant que la 3.5 a <code>asyncio.async</code>, mais 3.7 considère ça une erreur.</p>
<p>Petit exemple avec <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=902788">l&#8217;impact sur debian</a>.</p>
<h2>Comment on aurait pu éviter ce merdier ?</h2>
<p>D&#8217;abord, il aurait fallu ne pas introduire asyncio à l&#8217;arrache. Dans mon <a href="http://sametmax.com/guido-van-rossum-soffre-des-vacances-permanentes/">&#8220;au revoir&#8221; à Guido</a>, je disais que je trouvais que les dernières fonctionnalités majeures de Python avaient été mises en oeuvre de manière précipitée.</p>
<p>Cela se vérifie encore et encore avec asyncio, dont il faudra que je fasse un article pour dire tout ce qui a mal tourné.</p>
<p>Casser la compatibilité ascendante dans une version mineure n&#8217;est pas acceptable, même si les dégâts sont limités et qu&#8217;on y survivra très bien. </p>
<p>Le fait qu&#8217;asyncio soit une API marquée comme &#8220;provisional&#8221; n&#8217;a jamais empêché quelqu&#8217;un d&#8217;appeler ses variables <code>async</code>. Après tout on utilise les threads depuis bien longtemps.</p>
<p>L&#8217;autre problème vient de l&#8217;amateurisme qui se glisse de plus en plus dans le dev. </p>
<p>C&#8217;est une bonne chose, parce que ça veut dire que la programmation est de plus en plus accessible et accueille de plus en plus de monde. </p>
<p>Mais cela veut dire aussi qu&#8217;une grosse part la population de programmeurs est aujourd&#8217;hui constituée de personnes qui n&#8217;ont ni les connaissances, compétences ou ressources pour faire les choses correctement.</p>
<p>On le voit particulièrement dans le monde JavaScript, ou c&#8217;est l&#8217;explosion (là encore, ça mérite un nouvel article). Mais l&#8217;exemple de la 3.7 nous montre que la communauté Python n&#8217;est pas immunisée, et je pense que le problème va s&#8217;amplifier.</p>
<p>Que veux-je dire par là ?</p>
<p>Et bien il y a 30 ans, cela ne serait pas venu à l&#8217;esprit de la plupart des devs de compiler quelques choses sans mettre les flags en mode parano pour voir ce qui allait péter. Après tout, quand on code en C, on sait que tout peut imploser à tout moment, alors la prudence est une question de culture.</p>
<p>Aujourd&#8217;hui par contre, la majorité des devs des langages haut niveau écrivent du code, font quelques tests à la main, et publient ça. D&#8217;autres les utilisent. Font des mises à jour en masse. Aucun ne prennent le temps ne serait-ce que d&#8217;activer les warnings les plus basiques.</p>
<p>Comme tout est facile à première vue, et c&#8217;est quelque chose dont on fait la promotion pédagogiquement parlant, car ça incite les gens à se lancer, on oublie la complexité inhérente à la programmation.</p>
<p>Mais il y a une différence colossale entre avoir un code qui marche une fois sur sa machine, et un code prêt pour la production.</p>
<p>Par exemple en Python, vous pouvez demander l&#8217;activation des <a href="http://sametmax.com/warning-technique-a-un-autre-developpeur-en-python/">warning</a> pour chaque appel avec:</p>
<pre lang="bash">python -Wd</pre>
<p>En 3.6, ça implique ceci:</p>
<pre lang="python">>>> def async():
...     pass
... 
<stdin>:1: DeprecationWarning: 'async' and 'await' will become reserved keywords in Python 3.7</pre>
<p>L&#8217;info a toujours été là. Prête à être utilisée.</p>
<p>Mais alors pourquoi ne pas afficher tous les warnings, tout le temps ?</p>
<p>Et bien si je le fais:</p>
<pre lang="bash">python -Wa</pre>
<p>Voilà ce que ça donne quand je lance juste le shell de python 3.6:</p>
<p><a href="https://0bin.net/paste/ArazA4+bjJ4V06Ql#8A0m+PI7EJcVhN6rwp76HwDbOQ2MWLRayO8IeArGr2N">Voir le code sur 0bin.</a></p>
<p>Vous comprenez donc bien que ce n&#8217;est PAS activé par défaut. En fait, originalement le message était dans le corps de l&#8217;article, mais j&#8217;ai du le mettre sur 0bin parce que ça faisait planter WordPress. Si.</p>
<p>A chaque upgrade, il est important de vérifier les warnings pour préparer ses migrations futures.</p>
<p>Oui, c&#8217;est du boulot.</p>
<p>En fait&#8230;</p>
<h2>La programmation, c&#8217;est BEAUCOUP de boulot</h2>
<p>Même si on arrive maintenant à extraire une frame vidéo en gif en une ligne de commande. </p>
<p>Surtout maintenant qu&#8217;on y arrive en fait, car on multiplie les agencements hétérogènes de boites noires pour créer nos merveilleux programmes qui font le café.</p>
<p>Alors on prend des raccourcis. </p>
<p>Et puis aussi, parce qu&#8217;on ne sait pas. Qui parmi les lecteurs du blog, pourtant du coup appartenant à la toute petite bulle des gens très intéressés par la technique, connaissaient le rôle des warnings et comment les activer ?</p>
<p>Mais ce n&#8217;est pas le seul problème. Il y a clairement une question d&#8217;attentes et de moyen. </p>
<p>L&#8217;utilisateur (ou le client) final veut toujours plus, pour moins cher, et plus vite !</p>
<p>Et le programmeur veut se faire chier le moins possible.</p>
<p>Comme la complexité des empilements d&#8217;abstractions augmente, cela conduit à ignorer ce sur quoi on se base pour créer ce qui doit combler notre satisfaction immédiate.</p>
<p>J&#8217;ai parlé d&#8217;amateurs plus haut.</p>
<p>Mais je ne parle pas simplement de mes élèves. De mes lecteurs.</p>
<p>Je parle aussi de moi.</p>
<p>Prenez <a href="https://github.com/sametmax/0bin">0bin</a> par exemple.</p>
<p>Il n&#8217;est plus à jour. Il n&#8217;a pas de tests unitaires. Il a des bugs ouverts depuis <stong>des années</stong>.</p>
<p>Ce n&#8217;est pas pro du tout.</p>
<p>Sauf que je ne suis pas payé pour m&#8217;en occuper, et c&#8217;est bien une partie du problème: nous sommes de nombreux bénévoles à faire tourner la machine a produire du logiciel aujourd&#8217;hui. Donc si je n&#8217;ai pas envie, fuck it !</p>
<p>Vous imaginez si l&#8217;industrie du bâtiment ou celle de l&#8217;automobile tournaient sur les mêmes principes ?</p>
<p>La moitié des dessins industriels faits par des bloggers, des étudiants, des retraités, des profs de lycées, des géographes, de biologistes et des postes administratifs ?</p>
<p>Des immeubles et des voitures dont des pièces sont fabriquées par des potes qui chattent sur IRC et s&#8217;en occupent quand ils ont le temps ? Gratuitement. Y compris le service après-vente.</p>
<p>Alors que les usagers veulent toujours plus: des normes sismiques et de la conduite autonome. Tout le monde le fait, alors la maison de campagne et la fiat punto, c&#8217;est mort, personne ne l&#8217;utilisera. </p>
<p>Difficile de maintenir la qualité à cette échelle. </p>
<p>Il y a tellement de demandes de dev, jamais assez d&#8217;offres, de ressources toujours limitées. </p>
<p>Et ça grossit. Ça grossit !</p>
<h2>Aides techniques</h2>
<p>Ceci dit, à l&#8217;échelle de la PSF, ça aurait dû être évité.</p>
<p>Avant d&#8217;aborder les aides techniques, il serait bon d&#8217;arrêter les conneries. Je me répète, mais c&#8217;était une vaste dauberie de faire passer <code>async/await</code> en mot clé avant Python 4.</p>
<p>J&#8217;ai parfaitement conscience du besoin de faire progresser un langage pour ne pas rester coincé dans le passé. Je suis pour <code>async/await</code>, très bonne idée, superbe ajout. Mettre un warning ? Parfait ! Mais on respecte semver s&#8217;il vous plait. Si vous avez envie de faciliter la transition, mettre un import <code>__future__</code>, et inciter les linters à faire leur taff.</p>
<p>En attendant, pour la suite, Python va faciliter le debuggage.</p>
<p>Par exemple, depuis la 3.7, les <code>DeprecationWarning</code> sont activés par défaut au moins dans le module <code>__main__</code>. Donc un développeur verra ses conneries bien plus rapidement.</p>
<p>E.G:</p>
<p>Imp est déprécié en 3.6, mais sans -Wd, on ne le voit pas:</p>
<pre lang="bash">$ python3.6
Python 3.6.5 (default, May  3 2018, 10:08:28) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import imp</pre>
<p>En 3.7, plein de modules importent <code>imp</code>, mais les <code>DeprecationWarning</code> ne sont pas montrés, car ça arrive dans des codes importés. En revanche, si dans le module principal, vous importez <code>imp</code>:</p>
<pre lang="bash">$ python3.7 
Python 3.7.0+ (default, Jun 28 2018, 14:08:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import imp
__main__:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
</pre>
<p>Ça donne une info importante, sans foutre un mur de warnings à chaque lancement.</p>
<p>Une autre aide est l&#8217;apparition, toujours en 3.7, du mode développement de Python avec <code>-X dev</code> qui active tout un tas de comportements aidant au développement:</p>
<ul>
<li>active <code>-Wd</code></li>
<li>appelle <code>PyMem_SetupDebugHooks</code></li>
<li>active <code>faulthandler</code></li>
<li>active le mode debug de asyncio</li>
<li>met <code>sys.flags.dev_mode</code> sur <code>True</code></li>
</ul>
<p>Évidemment, tout ça ne sert pas à grand-chose si on ne sait pas ce qu&#8217;il faut en faire. Et ça demande du temps et du travail, ce que l&#8217;amateurisme ne permet pas forcément.</p>
<p>Enfin je dis ça. La plupart des employeurs s&#8217;attendent à tout, tout de suite également. Donc au final, n&#8217;est-ce pas la culture générale de notre industrie qui est en train de virer dangereusement vers le vite fait mal fait ?</p>
<p>Même si il y a clairement une question de compétence (un prof de maths est généralement compétent en maths, alors que j&#8217;attends toujours de rencontrer un prof d&#8217;info qui est capable de mettre quelque chose en prod), la pression du marché a créé des attentes impossibles&#8230;</p>
<p>L&#8217;informatique n&#8217;existe comme secteur économique que depuis quelques décennies, contre des siècles pour la plupart des autres disciplines scientifiques. Pourtant on exige d&#8217;elle le même niveau de productivité. Il a bien fallut rogner quelque part, et c&#8217;est la fiabilité qu&#8217;on a choisit.</p>
<p>Quand il y 20 ans, on rigolait en comparant le debuggage de Windows a la réparation d&#8217;une voiture, et la punchline sur le redémarrage, ce n&#8217;était pas grave: un peu de virtuel dans un monde plein d&#8217;encyclopédies papier, de cabines ou bottins téléphoniques et autres cartes routières.</p>
<p>Aujourd&#8217;hui que notre monde entier dépend du fonctionnement de nos conneries codées à l&#8217;arrache, c&#8217;est plus emmerdant. Et ça explique aussi pourquoi le téléphone de ma grand mère fonctionne toujours mieux pour faire des appels que mon putain de smartphone a 600 euros. Mais je peux draguer une meuf par texto en faisant caca à l&#8217;aéroport. Tout a un prix.</p>


feed_id: http://sametmax.com/?p=24942
title: Sam ne répondra plus
uri: Sam-ne-répondra-plus-Recently-updated
url: http://sametmax.com/sam-ne-repondra-plus/
content:
<p>Si vous nous avez écrit un email, vous savez qu&#8217;on a tendance a être lents pour répondre. En fait, parfois plus d&#8217;un an :)</p>
<p>Mais que ce soit sur <a href="https://twitter.com/sam_et_max">twitter</a>, <a href="https://www.reddit.com/r/sametmax/">reddit</a>, <a href="http://indexerror.net/">indexerror</a>, <a href="https://framapiaf.org/web/accounts/28154">mastodon</a>, les commentaires du blog ou par email, on finit par répondre à tout le monde. Les ratés existent, mais ils sont rares. La seule catastrophe étant notre bug tracker, parce que j&#8217;en fais suffisamment au boulot pour ne pas avoir le courage de le faire sur mon temps libre.</p>
<p>Gérer toute cette communauté, ça a un coût. J&#8217;y ai joyeusement participé pendant toutes ces années, parce que j&#8217;aime profondément aider les gens.</p>
<p>Notez que je ne me prends pas pour mère Thérésa, à moins qu&#8217;elle ai déjà fait du SM et vendu du viagra illégalement. Mais donner un coup de main a toujours été quelque chose d&#8217;important pour moi.</p>
<p>C&#8217;est la raison pour laquelle j&#8217;aime donner des formations. Parfois gratuitement. Parfois dans le cadre associatif.</p>
<p>C&#8217;est la raison pour laquelle je me déplace à des confs bien loin pour donner des talks même si personne ne sait que c&#8217;est moi. Parfois je discute avec un groupe de gens enthousiastes de ce super site NSFW. C&#8217;est vrai qu&#8217;il est bien. Vous l&#8217;avez connu comment ?</p>
<p>C&#8217;est la raison de la qualité des articles du blog également. Je passe un temps déraisonnable à me demander comment je vais pouvoir aider au mieux le lecteur avec une explication. Il m&#8217;est arrivé plusieurs fois de passer une journée entière sur un seul article compliqué, aux dépens d&#8217;un client que j&#8217;aurais pu facturer. Si on devait chiffrer le coût de ce site, je pense que ça me paierait un joli tour du monde.</p>
<p>Alors oui, ça a un prix, et je l&#8217;ai payé avec plaisir. Mes amis, qui m&#8217;ont entendu cracher sur les réseaux sociaux, ont même été étonnés de voir mon investissement sur Hacker news ou Twitter, au fil des années.</p>
<p>En cette fin 2018, je vais changer mon implication. J&#8217;ai envie de récupérer du temps libre, diminuer la tentation des interruptions et renforcer ma capacité d&#8217;attention, ce qui veut dire trancher dans le gras des distractions. Moins de surf sans but, moins de streaming, et moins de présence en ligne.</p>
<p>J&#8217;ai pensé à arrêter complètement le blog, mais soyons honnête, je n&#8217;écris plus au dixième du rythme de ses débuts, donc ça ne me prend pas si longtemps. Et un article de  temps en temps, c&#8217;est thérapeutique. Je pense que j&#8217;ai besoin de mon troll JavaScript annuel pour des raisons de santé.</p>
<p>Ce qui me prend du temps par contre, c&#8217;est tout ce qui est autour des articles.</p>
<p>Donc, à partir de cette semaine, je vais arrêter de répondre sur Twitter, le subreddit (qui n&#8217;a de toute façon jamais pris) et indexerror. Twitter en particulier sera donc de nouveau en sens unique, comme à nos touts débuts: je poste, et je ne réponds pas.</p>
<p>Pour les commentaires du blog, j&#8217;ai fermé la création de compte, et j&#8217;ai autorisé les commentaires uniquement à ceux qui avaient déjà un compte. Je ne répondrai pas pour autant, et je sais que la communauté existante ne foutra pas le bordel, tout en leur permettant de glisser les corrections des mes coquilles débiles.</p>
<p>Pour mastodon, je vais fermer le compte complètement. Enfin le passer en privé et l&#8217;oublier car framapiaf ne permet pas la supression. L&#8217;expérience est réussie, je pense que c&#8217;est une bonne plateforme, mais le ratio taff/retour est trop bas pour mes nouveaux objectifs.</p>
<p>Quant aux mails, pour le moment je garde le canal ouvert. Ce qui devrait me permettre du coup de répondre beaucoup, beaucoup plus rapidement.</p>
<p>Je vous aime quand même, hein.</p>


feed_id: http://sametmax.com/?p=24956
title: Programmation par contrat avec assert
uri: Programmation-par-contrat-avec-assert
url: http://sametmax.com/programmation-par-contrat-avec-assert/
content:
<p>Le mot clé <code>assert</code> est populaire en Python essentiellement grâce à la lib pytest, dont on vous a parlé dans <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-3/">le dossier sur les tests unitaires</a>.</p>
<p>En dehors de ce cas d&#8217;usage, personne ne comprend bien son utilité. </p>
<p>Déjà, dans les tutoriaux, on vous signale de ne pas l&#8217;utiliser pour faire des vérifications importantes, à cause d&#8217;une particularité d&#8217;<code>assert</code>: il peut disparaitre à tout moment ! </p>
<p>En effet, si vous lancez Python toutes voiles dehors avec l&#8217;option <code>-o</code> (pour &#8220;optimize&#8221;), les lignes contenant ce mot clé sont ignorées.</p>
<p>Alors, mille millions de mille sabords, pourquoi se faire chier à avoir ajouté ce truc ?</p>
<p>A quoi un machin qui peut disparaitre à tout instant peut-il bien servir ?</p>
<p>Well, it&#8217;s not a bug, it&#8217;s a feature, my dear.</p>
<p>Voyez-vous, on connait souvent le premier effet kisskool d&#8217;<code>assert</code>:</p>
<pre lang="python">
    assert condition
</pre>
<p>Et si la condition est fausse, on se tape une exception <code>AssertionError</code>.</p>
<p>En revanche, ce que les gens savent moins, c&#8217;est qu&#8217;il existe une seconde forme, beaucoup plus utile:</p>
<pre lang="python">
    assert condition, "Message en cas d'erreur"
</pre>
<p>Qui fait tout pareil, mais permet de donner un feedback a qui tombe sur l&#8217;erreur susnommée.</p>
<p>Et c&#8217;est là que c&#8217;est intéressant: parce que ça vous permet de mettre des vérifications complexes dans le code, qui vont permettre aux devs d&#8217;éviter les âneries. C&#8217;est ce qu&#8217;on appelle un contrat.</p>
<p>Imaginez une fonction qui prend en paramètre une valeur, qui est la clé d&#8217;un dictionnaire:</p>
<pre lang="python">
    ARTIBUSES = {
        'truc': 1,
        'bidule': 1,
        'machin': '2',
        'chose': '3',
        'chouette': '3',
        'foo': '4',
        # ...
    }
    
    def souquer_les_artibuses(artibuse):
    
        target = ARTIBUSES[artibuse]
        # un code de souquage professionnel s'ensuit
</pre>
<p>Si quelqu&#8217;un utilise votre code, et insère la mauvaise artibuse (le vil flibustier !), notre fonction va (s&#8217;)échouer sur une <code>KeyError</code>. Ceci va obliger le contrevenant (le perfide faquin !) à regarder dans le code source et comprendre le code pour trouver la source de son désarroi. Quelle perte de temps pour notre dev (le fils de pute !).</p>
<p>Une solution est alors de mettre:</p>
<pre lang="python">
    def souquer_les_artibuses(artibuse):
        if artibuse not in ARTIBUSES:
            raise ValueError(
                f"'{artibuse}'' n'est pas une artibuse valide. "
                f"Utilisez une valeur parmi: {', '.join(ARTIBUSES)}"
            )
        target = ARTIBUSES[artibuse]
</pre>
<p>Et c&#8217;est certes une bonne solution, claire et explicite. </p>
<p>Mais elle a un défaut majeur: à chaque appel, on rajoute le poids d&#8217;un test qui n&#8217;a aucun intérêt pour le fonctionnement normal du programme. En fait, la majorité des appels de cette fonction se feront avec les bonnes valeurs (logique sinon le code planterait), et donc notre test est un poids superflu.</p>
<p>Ce problème se cumule quand les tests deviennent plus nombreux, plus complexes, et plus lourds, tandis que la fonction est appelée de plus en plus de fois.</p>
<p>Comment concilier donc son besoin impérieux d&#8217;aider son prochain, qui est probablement soi-même un vendredi à 3h du mat après un push qu&#8217;on n’aurait pas du faire en fin de semaine, et éviter ce gâchis de ressource ?</p>
<p>Ventre-saint-gris de sa race ! Avec <code>assert</code> bien entendu !</p>
<pre lang="python">

    def souquer_les_artibuses(artibuse):

        assert artibuse in ARTIBUSES, (
            f"'{artibuse}'' n'est pas une artibuse valide. "
            f"Utilisez une valeur parmi: {', '.join(ARTIBUSES)}}"
        )

        target = ARTIBUSES[artibuse]
</pre>
<p>En dev, ou quand on debug en production, on obtient toutes les vérifications et infos nécessaires. Le contrat à remplir avec notre fonction est vérifié. On peut mettre autant de clauses à notre contrat qu&#8217;on le souhaite, aussi lourdes qu&#8217;on veut ! </p>
<p>Quand on est prêt à relancer la prod en mode propre, on exécute tout avec <code>-o</code></p>
<p>Les vérifications faites en amont d&#8217;une fonction sont ce qu&#8217;on appelle des pré-conditions dans le jargon de la programmation par contrat. Ce sont les plus faciles à comprendre et les plus courantes. On peut néanmoins faire également des vérifications à la fin de la fonction, qui permette de vérifier qu&#8217;on est bien dans un état cohérent à la sortie de celle-ci. </p>
<p>C&#8217;est ce qu&#8217;on appelle des post-conditions: c&#8217;est moins courant, et moins facile à écrire, mais très puissant car on se souci d&#8217;un état final (est-ce que mon résultat est > 3 ?), et non de comment on y arrive. Un moyen bien plus souple d&#8217;attraper des erreurs plutôt que de chercher toutes les combinaisons de ce qu&#8217;on peut mal faire.</p>
<h2>Effets secondaires de -o</h2>
<p>Le saviez-vous ? Python vient aussi avec une variable magique, <code>__debug__</code>, qui est à <code>True</code> par défaut. Utiliser <code>-o</code> met cette variable a <code>False</code>. Plus fort encore, toute condition sur <code>__debug__</code> sera retirée du code !</p>
<pre lang="python">
if __debug__:
    un_dump_log_de_porc()
</pre>
<p>Pouf, avec <code>-o</code>, plus de dump.</p>
<p>Il existe même <code>-oo</code> pour retirer en plus les docstrings, et économiser un peu de mémoire.</p>
<h2>Le problème avec assert</h2>
<p>Le problème avec <code>assert</code>, c&#8217;est vous. Enfin je dis vous, le vous du passé, celui qui ne savait pas. En effet, plein de devs vont utiliser des <code>assert</code> dans leur code sans penser à mal. Et vous arrivez avec votre <code>-o</code>, et boom, le code est tout cassé. C&#8217;est bien con de ne pas pouvoir stripper ses <code>assert</code> à soi sous prétexte qu&#8217;une dépendance est codée par un <del>connard</del> Bachi-bouzouk.</p>
<p>Or <code>assert</code> est très souple, et permet de tester littéralement n&#8217;importe quoi. Du coup, cela demande un peu d&#8217;expérience pour savoir quand l&#8217;utiliser, et quand ne pas le faire.</p>
<p>Le concept général est: si votre erreur concerne la fonctionnalité fondamentale de votre fonction, levez toujours une exception. Si en revanche vous testez si les valeurs des paramètres correspondent à quelque chose de sain, <strong>et qu&#8217;une erreur n&#8217;aurait pas d&#8217;effet de bord</strong>, vous pouvez (ce n&#8217;est pas du tout obligatoire, une exception normale reste un usage correct) utiliser <code>assert</code>.</p>
<p>Donc, n&#8217;utilisez pas assert pour tester la logique de votre programme, ni pour protéger l&#8217;intégrité de vos données face à une erreur.</p>
<p>Une dernière chose: n&#8217;utilisez pas <code>assert</code> pour fournir un contrat basé sur les types (comme par exemple, appeler <code>isinstance()</code>), puisque mypy et les <a href="http://sametmax.com/point-rapide-sur-les-types-hints/">types hints</a> le font déjà et qu&#8217;ils sont maintenant très agréables à utiliser.</p>


feed_id: http://sametmax.com/?p=25060
title: Vive setup.cfg (et mort à pyproject.toml) !
uri: Vive-setup-cfg-(et-mort-à-pyproject-toml)
url: http://sametmax.com/vive-setup-cfg-et-mort-a-pyproject-toml/
content:
<p>Après un long débat sur <a href="https://news.ycombinator.com/item?id=18612905">hackernews</a>, qui n&#8217;est que le reflet de toutes les conversations que j&#8217;ai déjà eues à ce sujet sur twitter, github, et divers mailling lists, il est grand temps de faire un article. Urgent même.</p>
<p>Est-ce que vous savez quel chemin de croix on a vécu avec le packaging Python durant ces 15 dernières années ?</p>
<p>D&#8217;abord on a <code>distutils</code>, <code>setuptools</code>, <code>distribute</code>, and <code>distribute2</code> qui ont tous été à un moment les &#8220;standards&#8221; recommandés pour packager une lib. Ensuite on a eu l&#8217;époque des <code>eggs</code>, <code>exe</code>, et autres trucs que <code>easy_install</code> allait chercher n&#8217;importe où dans la nature en suivant aveuglément des liens sur PyPi. Sans compter les machins qu&#8217;il fallait compiler à tout bout de champ. Et puis rien n&#8217;était chiffré au download, <code>pip</code> n&#8217;était pas packagé avec Python, il crevait sur des erreurs stupides type encodage mal géré&#8230;</p>
<p>À ça se rajoute que virtualenv était un truc à part, avec plein de concurrents, et linkait les packages système par défaut. Sans oublier qu&#8217;on avait pas <code>Python -m</code>. </p>
<p>Bref, le packaging Python, ça a été vraiment la merde. Avec en plus une doc de merde.</p>
<p>Aujourd&#8217;hui, le standard <code>wheel</code> a énormément amélioré la donne. On a des tutos corrects (ex: <a href="http://sametmax.com/creer-un-setup-py-et-mettre-sa-bibliotheque-python-en-ligne-sur-pypi/">notre tuto sur comment créer son package avec setup.py</a>). <code>ensurepip</code> fait qu&#8217;on a une version récente du truc presque partout. </p>
<p>En gros, notre situation est stable, saine. Améliorable de bien des façons, certes, mais un bon socle sur lequel s&#8217;appuyer.</p>
<h2>
    Arrive setup.cfg<br />
</h2>
<p>En 2016, l&#8217;équipe de <a href="https://pypi.org/project/setuptools/">setuptools</a>, la lib utilisée par à peu près tout le monde pour créer des packages en Python aujourd&#8217;hui, a créé le format <code>setup.cfg</code>, un fichier INI dont le but est de remplacer <code>setup.py</code>. </p>
<p>Le problème de <code>setup.py</code> c&#8217;est que c&#8217;est du code Python exécutable, et en plus dépendant de la lib setuptools. Cela empêche non seulement l&#8217;interfaçage avec des outils externes, mais aussi freine l&#8217;émergence de nouveaux outils.</p>
<p>En effet, il y a un désir de continuer à améliorer la situation du packaging en Python, comme on peut le voir avec des projets comme <a href="https://github.com/pypa/pipenv">pipenv</a> ou <a href="https://github.com/sdispater/poetry">poetry</a> (je recommande d&#8217;ailleurs fortement ce dernier, et je vous invite à voter sur <a href="https://github.com/sdispater/poetry/issues/704">cette issue</a> pour enfoncer le clou).</p>
<p><code>setup.cfg</code> est la suite logique de tout ça, un format en texte brut, facile à manipuler pour le reste du monde. </p>
<p>Et ça a été bien fait:</p>
<ul>
<li>
        <code>setup.cfg</code> marche out of the box. Il n&#8217;y a rien à faire de particulier : si vous aviez un <code>setup.py</code>, vous pouvez juste le convertir en <code>setup.cfg</code>. Si vous avez un nouveau projet, vous pouvez juste écrire le <code>setup.cfg</code>. Il n&#8217;y a pas de piège. Ça marche depuis&#8230; 2016. Ouais.
    </li>
<li>
        <code>setup.cfg</code> a <a href="https://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files">une documentation décente</a>. Si, si. C&#8217;est très améliorable, mais mieux que tout ce qu&#8217;on a jamais eu pour les premières années de <code>setup.py</code>
    </li>
<li>
        <code>setup.cfg</code> couvre la plupart des cas de figure que <code>setup.py</code> faisait et se permet de rajouter des goodies très cools. <code>version = attr: src.__version__</code> inclue la version depuis __init__.py,  <code>"options.data_files"</code> remplace le MANIFEST et <code>"license =  file: LICENCE.txt"</code> injecte le corps de la licence depuis un fichier texte. Tous les hacks à la noix de <code>setup.py</code> ? Fini.
    </li>
<li>
        C&#8217;est simple à utiliser. Voici quelques projets pour démontrer le bouzin: <a href="https://github.com/jleclanche/python-bna/blob/master/setup.cfg">exemple 1</a>, <a href="https://github.com/dj-stripe/dj-stripe/blob/master/setup.cfg">exemple 2</a>, <a href="https://github.com/jazzband/django-oauth-toolkit/blob/master/setup.cfg">exemple 3</a>, <a href="https://github.com/jazzband/django-push-notifications/blob/master/setup.cfg">exemple 4</a>. Ça se comprend même sans lire la doc !
    </li>
<li>
        C&#8217;est compatible avec tous les outils legacy. En fait, il suffit de créer un fichier <code>setup.py</code> avec une seule ligne dedans (<code>import setuptools; setuptools.setup()</code>) et pouf, tout le worflow d&#8217;avant marche: <code>python setup.py develop</code>, <code>python setup.py sdist upload</code>, etc. Du coup, tout ce qui comprenanait <code>setup.py</code> (c&#8217;est à dire le putain de monde entier en Python) marche avec <code>setup.cfg</code>.
    </li>
</ul>
<p>Donc setup.cfg, malgré des lacunes, c&#8217;est sympa.</p>
<h2>
    Setup.cfg, ou es-tu ?<br />
</h2>
<p>&#8220;Attend une minute, si c&#8217;est si bien que ça, pourquoi j&#8217;en ai jamais entendu parler ? Moi on m&#8217;a dit que <code>setup.cfg</code> il servait à rien&#8230;&#8221;</p>
<p>Je ne vous le fais pas dire ! </p>
<p>Je n&#8217;ai aucune idée de la raison pour laquelle cette information ne circule pas plus. La seule raison pour laquelle je l&#8217;ai trouvée c&#8217;est parce que je passe des heures à faire de la veille informationnelle en Python, et que je suis tombé dessus au détour d&#8217;un carrefour, dans une ruelle sombre du Web. Et que j&#8217;ai pris le temps et le risque de le tester sur un de mes projets pour vérifier que oui, ça marche comme prévu.</p>
<p>Même la doc Python <a href="https://docs.python.org/3.7/distutils/configfile.html">vous fait croire</a> que <code>setup.cfg</code> c&#8217;est un artéfact vaguement utile pour une pauvre option monoligne.</p>
<p>Et merde, j&#8217;ai déjà écrit 900 articles sur ce blog, je ne peux pas mettre à ma charge d&#8217;avertir tout le monde pour chaque truc à savoir sur Python.</p>
<p>C&#8217;est comme pour le <code># -*- coding: utf-8 -*-</code>. Un jour un mec utilisant Emacs a écrit un tuto avec ça, et tout le monde a copié-collé les hiéroglyphes alors qu&#8217;en fait <code># coding: utf8</code> est parfaitement valide. Ou comme <a href="http://nuitka.net/">nuikta</a>, qui permet de compiler de Python de manière fiable, et que personne ne connait. Combien de temps doit-on gâcher avec des trucs comme ça ?</p>
<h2>
   pyproject.toml vient foutre le bordel<br />
</h2>
<p>Maintenant, figurez-vous que nous avons un groupe de personnes chargées de faire évoluer la situation du packaging, la Python Packaging Authority, ou <a href="https://www.pypa.io/en/latest/
">PyPA</a>.</p>
<p>Une très bonne initiative, vu que le free-for-all du passé ne nous avait pas trop réussi. Et un succès puisque la situation actuelle en packaging Python est maintenant beaucoup plus propre.</p>
<p>Et on en a besoin. En effet, <code>setup.cfg</code> doit être amélioré car il a certains défauts. Le format n&#8217;est pas parfaitement standardisé. Seule la doc fait figure de description, et pour l&#8217;instant <code>setup.cfg</code>, c&#8217;est whatever <a href="https://docs.python.org/3/library/configparser.html">configparser</a> comprends, sachant que <code>configparser</code> parse les trucs au motoculteur, et selon la version de Python. C&#8217;est pas gravissime, et ça n&#8217;a pas vraiment été un problème jusque là, mais pour la pérennité de la chose, une consolidation est nécessaire. On doit avoir une spec solide, un parseur robuste et stable, etc.</p>
<p>Sachant la purge qu&#8217;a été l&#8217;historique du packaging en Python, on s&#8217;attend donc a ce que la PyPA fasse le choix de standardiser <code>setup.cfg</code>, qui marche depuis 2 ans, fait le job, est compatible avec l&#8217;existant et résout déjà le problème de permettre au reste du monde de manipuler les données du package en texte brut. Puis, comme un bon groupe de décision sage, elle va proposer des solutions incrémentales aux défauts de <code>setup.cfg</code> et son écosystème. </p>
<p>Un exemple possible serait de s&#8217;allier avec l&#8217;équipe de <code>setuptools</code> pour figer le format <code>setup.cfg</code>, clarifier les edge cases de ce INI en particulier, et si besoin, créer une alternative a <code>configparser</code> (ou figer <code>configparser</code>) afin d&#8217;obtenir une implémentation de référence irréprochable pour parser le format. Puis désigner ce format comme le nouveau standard, en version 1 implicite, et le documenter puis en faire la promotion afin que tous les nouveaux outils puissent l&#8217;utiliser. Ensuite, ayant identifié des limitations, on crée le successeur de ce format, qui aura le même nom, mais un header de version qui lui sera explicite afin de permettre aux parseurs de s&#8217;adapter. Et on fait en sorte que cette nouvelle version soit plus propre, plus belle, super green. Et on l&#8217;introduit aussi progressivement et en douceur qu&#8217;un sex toy anal.</p>
<p>Bref, on s&#8217;attend à ce que la PyPA nous amène vers une totale liberté de pensée cosmique vers un nouvel âge réminiscence.</p>
<p>Sauf que non.</p>
<p>Ces ânes ont décidé&#8230;  de créer <a href="https://www.python.org/dev/peps/pep-0518/">un nouveau format</a> et ignorer tout l&#8217;existant. </p>
<p>Fuck. That. Je hais que ce dessin de XKCD puisse être d&#8217;actualité encore et encore, chaque mois que l&#8217;humanité passe:<br />
<img src=" https://imgs.xkcd.com/comics/standards.png" alt="Le packaging en Python, c'est une forme de solidarité masochiste avec la communauté JS" /></p>
<p>Je ne comprends pas cette décision, et leurs justifications sont d&#8217;une grande faiblesse, pour ne pas dire insultante pour une communauté qui en a marre de payer le prix de l&#8217;égo des gens qui ont envie d&#8217;avoir leur nom sur la nouvelle barre de fer officielle.</p>
<p>C&#8217;est d&#8217;autant plus étrange que la PyPA n&#8217;est pas composée de cons. Non. On a Brett Cannon (core dev, qui fait un travail exceptionnel avec Python VSCode), Nathaniel Smith (qui nous a révolutionné l&#8217;async avec trio) et Kenneth Reitz (l&#8217;auteur de Python requests).</p>
<p>Comment ce pet de cerveau a-t-il pu émané de ces brillantes personnes, je ne le sais.</p>
<p>Mais je vous invite tous à non seulement utiliser <code>setup.cfg</code> en masse, mais aussi à activement contester cette décision sur tous les mediums à votre disposition. </p>
<p>Parce qu&#8217;évidemment je l&#8217;ai faits, et comme d&#8217;hab, ils font la sourde oreille. Et on va en payer le prix. Mais bon, depuis le temps, vous avez l&#8217;habitude. C&#8217;est pas comme si j&#8217;avais pas déjà annoncé que redux et dockers étaient overkill pour la plupart des projets, que le NoSQL allait avoir un retour de baton, que vue était génial, flask PAS pour les débutants, bitcoin intéressant, pipenv &#8211;three stupide, python parfait pour l&#8217;enseignement&#8230; des années avant. Pour les consultations de boule de cristal, c&#8217;est uniquement le mardi à 15h.</p>
<h2>
    N&#8217;est-ce pas trop tard ?<br />
</h2>
<p>Au contraire, c&#8217;est exactement le bon moment. Le format le plus utilisé actuellement n&#8217;est ni le setup.cfg, ni le pyproject.toml, mais toujours le bon vieux setup.py. En fait, n&#8217;en déplaise aux defenseurs de pyproject.toml qui veulent nous faire croire que le projet est bien plus populaire et avancé qu&#8217;il ne l&#8217;est vraiment, il vaut l&#8217;équivalent d&#8217;un draft de proposal en beta testing. Une simple recherche github retourne:</p>
<ul>
<li>
        <a href="https://github.com/search?q=filename%3Asetup.py">setup.py: 1,259,007 results</a>
    </li>
<li>
        <a href="https://github.com/search?q=filename%3Asetup.cfg">setup.cfg: 165,716 results</a>
    </li>
<li>
        <a href="https://github.com/search?q=filename%3Apyproject.toml">pyproject.toml: 2,137 results </a>
    </li>
</ul>
<p>De toute façon la transition sera longue, et les outils commencent à peine à supporter le nouveau format. En fait, ils ne sont même pas d&#8217;accord sur comment l&#8217;utiliser. On n&#8217;a pas de standard pour le lock file (pipfile semble se dégager, mais n&#8217;est pas enterriné) et les outils utilisent pyproject.toml en créant une section custo dedans au lieu des champs standardisés (poetry), voire pas du tout comme pipenv. De plus, setup.cfg est déjà utilisé dans la nature (voir les exemples plus haut).</p>
<p>Par ailleurs, extraire les données de setup.cfg plutôt que de pyproject.toml n&#8217;est pas très compliqué, les outils de packaging n&#8217;ont qu&#8217;une toute petite partie de leur code dédié à la gestion du fichier, le reste c&#8217;est la logique de management des dépendances, le téléchargement, la command line, le virtualenv, etc. Ils peuvent par ailleurs tout à fait supporter les deux pendant la transition.</p>
<p>Vu que c&#8217;est nous qui allons nous coltiner les conséquences du choix pour les 10 prochaines années à venir, autant élever la voie. D&#8217;autant que, surprise, ça ne coûte quasiment rien à la majorité des projets de migrer ou commencer avec setup.cfg. Tout marche déjà, et on peut produire de jolies wheels. On ne peut pas dire autant de pyproject qui demande d&#8217;adopter des outils tout neufs et qui doivent encore faire leur preuve. Aussi, bonne chance pour faire marcher votre toolchain de CI avec, j&#8217;ai essayé, et croyez moi c&#8217;est relou.</p>
<p>Maintenant, j&#8217;aime que le packaging avance. J&#8217;aime même les nouveaux outils comme poetry. Mais la suite n&#8217;est pas inéluctable, et on peut concilier modernité avec sanité.</p>


feed_id: http://sametmax.com/?p=25104
title: Le don du mois: Libre Office
uri: Le-don-du-mois-Libre-Office-Recently-updated
url: http://sametmax.com/le-don-du-mois-libre-office/
content:
<p>Microsoft Office est un bon produit. Voilà, je l&#8217;ai dit. Je peux ne pas apprécier Microsoft en tant qu&#8217;entreprise, reprocher de nombreux défauts à ses bébés, mais être objectif sur certains points: Excel, malgré ses bugs, reste la meilleure expérience de tableur au monde, .Net est une technologie très propre, et VSCode est un superbe éditeur que j&#8217;ai par ailleurs adopté.</p>
<p>Seulement voilà, je n&#8217;ai nullement l&#8217;intention de soutenir des formats propriétaires, l&#8217;obsolescence programmée, et l&#8217;abus de position dominante. Au contraire, je préfère soutenir le logiciel libre, les standards ouverts et le partage.</p>
<p>Et c&#8217;est là que Libre Office entre en jeu.</p>
<p>Je l&#8217;utilise donc au quotidien, pour faire des rapports, des lettres, des calculs, etc. Bien que je sois très à l&#8217;aise avec ma machine, j&#8217;utilise des fonctions relativement peu avancées, et ce logiciel comble donc tous mes besoins.</p>
<p>Malheureusement, Libre Office souffre de gros problèmes d&#8217;ergonomie, et pire encore, de fiabilité. Sa stabilité est douteuse, et en plus de la frustration liée au plantage, il m&#8217;arrive de perdre du travail, chose qui me rend furieux.</p>
<p>Je comprendrais donc parfaitement que quelqu&#8217;un choisisse de ne PAS utiliser Libre Office, pour toutes ces raisons.</p>
<p>Personnellement, j&#8217;ai la politique inverse, et j&#8217;utilise Libre Office pour les soutenir, et je vais donc reporter les bugs et autres problèmes quand j&#8217;en ai le temps. J&#8217;ai peu de temps en ce moment, donc je choisis de contribuer par don, ce qui j&#8217;espère aidera les auteurs à dépasser ces hics. Un jour peut-être.</p>
<p>Un peu comme Firefox que j&#8217;ai gardé pendant des années alors qu&#8217;il était inférieur à Chrome, jusqu&#8217;à ce que, soudain, il redevienne non seulement aussi rapide, mais rajoute des fonctionalités inédites comme les tab containers que n&#8217;a pas la concurrence.</p>
<p>Et voici donc un don de 50 euros pour cet excellent projet, qui derrière ces soucis, permet quand même à peu de frais de faire des choses absolument incroyables, le tout dans le respect de la communauté humaine.</p>
<p>Bien entendu, je vous invite à <a href="https://fr.libreoffice.org/donate/">faire de même</a>.</p>


feed_id: http://sametmax.com/?p=25112
title: Ecouteurs bluetooth
uri: Ecouteurs-bluetooth-Recently-updated
url: http://sametmax.com/ecouteurs-bluetooth/
content:
<p>Je mets une fortune dans mes casques, que j&#8217;abime et perds en plus très souvent. Or, j&#8217;ai toujours eu une relation mitigée avec les écouteurs Bluetooth (et le BT en général d&#8217;ailleurs&#8230;), et je suis assez froissé par la tendance à supprimer les jacks.</p>
<p>Le fil d&#8217;un ami m&#8217;a fait pourtant tester les airpods, et j&#8217;ai été surpris par la qualité du son et la facilité d&#8217;usage. J&#8217;ai cherché un concurrent.</p>
<p>Après enquête, j&#8217;ai tenté les <a href="https://www.jabra.com/bluetooth-headsets/jabra-elite-65t">Jabra Elite 65T</a>. Après des mois d&#8217;usage, voici ce que je peux en dire&#8230;</p>
<p>Les plus:</p>
<ul>
<li>
        Le son est excellent, particulièrement pour la taille sur du sans-fil, y compris sur du<br />
    classique, et les basses ne sont pas sur amplifiées comme c&#8217;est souvent le cas pour plaire à la masse;</li>
<li>
        C&#8217;est confortable. Je les porte des heures;
    </li>
<li>
        5h d&#8217;autonomie + 5 de secours avec le boitier. Je suis arrivé au bout seulement 2 fois<br />
    malgré des mois d&#8217;usage, donc pas un problème. Mais c&#8217;est vrai que les airpods font le double.</li>
<li>
        La synchro Bluetooth est parfaite avec portable récent (donc le messie bt5): rapide,<br />
    sans galère. Quand on ressort les écouteurs du boitier, le pairing est automatique et transparent.</li>
<li>
        Le boitier de transport / chargeur / batterie de secours fonctionne à merveille.
    </li>
<li>
        L&#8217;attache dans l&#8217;oreille est excellente. On peut se faire secouer, courir, faire du<br />
    yoga&#8230; Ça bouge pas.</li>
<li>
        On peut écouter avec une seule oreille, mais seulement la droite.
    </li>
<li>
        Les appels sont limpides, on a du mal à croire que ce petit micro marche si bien.
    </li>
<li>
        Après la perte inéluctable des deux écouteurs, j&#8217;ai fait une demande au SAV. 40 Euros,<br />
    et reçu en 2 jours. Beau. Resyncro instantanée une fois placée dans le boitier.</li>
<li>
        De vrais boutons qui permettent de contrôler pleinement la lecture, et pas juste 3<br />
    tapotements limités et difficiles en mouvement.</li>
<li>
        3 tailles embout. Et choisir les bons a un gros impact sur le confort. Les<br />
    intra-auriculaires à taille unique, ça m&#8217;a toujours laissé perplexe.</li>
<li>
       Bonne isolation du son extérieur.
    </li>
<li>
        Retirer un écouteur coupe la musique.
    </li>
<li>
        Zéro latence. J&#8217;ai eu des écouteurs BT moins cher, et regarder des films avec était un<br />
    enfer. Là c&#8217;est fantastique, avec VLC ou Netflix dans le train, on se fait plaisir.</li>
</ul>
<p>Les moins:</p>
<ul>
<li>
        180 euros à l&#8217;achat. Bam.
    </li>
<li>
        Le boitier est trop gros. Contrairement à celui des airpords, le mettre dans la poche n&#8217;est<br />
    pas aussi discret qu&#8217;une boite d&#8217;allumettes.</li>
<li>
        Il y a un mode pass-through si vous êtes en vélo et que l&#8217;isolation sonore est dangereuse,<br />
    mais il est pas ouf. Mieux vaut reste sur une écoute d&#8217;une oreille.</li>
<li>
        Certains comportements sont contre-intuitifs: retirer l&#8217;écouteur gauche coupe la musique,<br />
    mais en fait on peut la relancer sur un seul écouteur en pressant le bouton principal. On peut aussi désactiver ce comportement via une app pour partager le son avec son voisin. Parfois l&#8217;écouteur gauche se met en veille quand il reste trop longtemps éloigné du droit, alors alors il faut une pression longue dessus pour le réveiller: le web est plein de gens qui croient que leur écouteur ne marche plus. Rien n&#8217;indique ces manipes sans un bon vieux RTFM.</li>
</ul>
<p>Finalement, ces petits joujoux m&#8217;ont réconcilié avec le sans-fil, et je n&#8217;ai presque plus touché à mes écouteurs ou mes baffles Bose. Certes, je n&#8217;écoute pas du flac, donc même si la qualité est bonne pour du mp3, j&#8217;imagine qu&#8217;un audiophile confirmé y trouvera à redire. </p>
<p>Ok, ok. Dans ces conditions, virez le jack&#8230; quand l&#8217;USB-C sera supporté partout.</p>


feed_id: http://sametmax.com/?p=25125
title: Le type bytes n’est pas du texte
uri: Le-type-bytes-n-est-pas-du-texte-Recently-updated
url: https://sametmax.com/le-type-bytes-nest-pas-du-texte/
content:
<p>J&#8217;ai beau essayer très fort de ne pas répondre en ligne, des fois <a href="https://news.ycombinator.com/item?id=18874232">je craque</a>. Mais je me soigne, globalement j&#8217;ai récupéré plein de temps, et ça se voit sur mon quotidien.</p>
<p>Et ce craquage, et bien il est cette fois dû à une totale mécompréhension des types de texte en Python 3.</p>
<p>Mais c&#8217;est bien normal: Python 3 ne gère pas le texte de la même manière que la grande majorité des langages de programmation, justement à cause de la débâcle qu&#8217;on a eue en Python 2. Du coup, de nombreux programmeurs arrivent avec leur expérience d&#8217;ailleurs, et tentent de l&#8217;appliquer tel un utilisateur de SVN migrant sur git. En surface ça semble coller, malheuseuement à l&#8217;usage, ça fait faire des erreurs.</p>
<p>Donc un peu d&#8217;explications.</p>
<p>En informatique, tout est une histoire de convention. On dit que tel mot clé a tel effet. Que tel nom suppose telle chose. Que tel code de retour implique telle erreur. Que tel schéma XML représente tel type de document.</p>
<p>Essentiellement, tout cela est arbitraire: des gens ont décidé qu&#8217;il en serait ainsi. Impossible de deviner que ce que fait <code>yield</code> ou <code>with</code> si vous n&#8217;avez pas d&#8217;expérience similaire avant. Impossible de savoir que le code <code>0</code> en bash ou <code>200</code> en HTTP signifie tout va bien sans qu&#8217;on vous transmette l&#8217;information, ou faire de nombreux tests.</p>
<p>Quand je dis arbitrairement, évidemment je ne veux pas dire complètement sans raison. Il y a des raisons techniques, politiques, économiques, et parfois esthétiques à ces conventions. Cela n&#8217;en retire en rien l&#8217;aspect parfaitement artificiel de ces choix.</p>
<p>La convention la plus omniprésente, et pourtant aujourd&#8217;hui la plus masquée dans un monde où on utilise massivement des langages de haut niveau comme Javascript, Ruby, PHP et Python, est celle de l&#8217;organisation des octets.</p>
<p>Musique !</p>
<p><iframe class='youtube-player' type='text/html' width='1170' height='689' src='https://www.youtube.com/embed/SBjQ9tuuTJQ?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' allowfullscreen='true' style='border:0;'></iframe></p>
<h2>   &#8230;je vois même plus le code : tout ce que je vois, c&#8217;est des blondes, des brunes, des rousses.<br />
</h2>
<p>Tout ce qui passe par nos ordinateurs n&#8217;est qu&#8217;une suite de zéros et de uns, que nous avons groupés par paquets de 8:</p>
<p>Seulement la grande révélation, le &#8220;aaaaaaahhhhh okayyyyyyy&#8221; qui arrive un jour dans toute vie de dev, c&#8217;est que <strong>ces paquets de 8 ne veulent rien dire.</strong> Rien. C&#8217;est nous qui avons décidé, arbitrairement encore une fois, de leur signification.</p>
<p>Vous voyez ce moment dans les films et séries où un personnage arrive à &#8220;lire du binaire&#8221; ?</p>
<div id="attachment_25161" style="width: 560px" class="wp-caption aligncenter"><a href="media/5aa4b089.IS1.png" data-original-source="http://sametmax.com/wp-content/uploads/2019/01/IS1.png" class="grouped_elements" rel="tc-fancybox-group25125"><img src="media/5aa4b089.IS1.png" data-original-source="http://sametmax.com/wp-content/uploads/2019/01/IS1.png" alt="Evidement, &quot;c&#039;est une representation binaire ASCII de coordonnées WGS 84 Web Mercator&quot; est plus dur à caser dans un dialogue" width="550" height="281" class="size-full wp-image-25161" /></a><p class="wp-caption-text">Evidement, &#8220;c&#8217;est une representation binaire ASCII de coordonnées WGS 84 Web Mercator&#8221; est plus dur à caser dans un dialogue</p></div>
<p>C&#8217;est de <a href="https://youtu.be/FvHHlKp923A?t=1132">l&#8217;enculage de dauphin</a>.</p>
<p>Le binaire n&#8217;est pas un langage, pas plus que les lettres &#8220;abcdefghijklmnopqrstuvwxyz&#8221;. Vous pouvez utiliser ces lettres pour représenter certains mots italiens, français, anglais, un nom propre (sans langue), le label d&#8217;un immeuble (sans langue encore) ou un chiffre latin. </p>
<p>Que veut dire &#8220;les gosses&#8221; ? Pour la même combinaisons de lettres, cela signifie &#8220;les enfants&#8221; avec la convention française européenne, et &#8220;les couilles&#8221; avec la convention québéquoise.</p>
<p>Pour le binaire c&#8217;est pareil, ce que veut dire un octet dépend de la convention que vous avez choisie.</p>
<p>Par exemple, que signifie cette suite d&#8217;octets ?</p>
<p><code>1100001 1100010 1100011 1100100</code></p>
<p>Bah rien. Mais <a href="https://www.youtube.com/watch?v=3c-irSUdij4">on peut lui donner un sens</a> en lui appliquant une convention.</p>
<p>Je peux lui appliquer la convention ASCII, et donc supposer que c&#8217;est un texte dans un certain format. Voici ce que ça donne en Python:</p>
<pre lang="python">     
>>> data = bytearray([0b1100001, 0b1100010, 0b1100011, 0b1100100])     
>>> print(data.decode('ascii'))     
abcd </pre>
<div id="attachment_25162" style="width: 310px" class="wp-caption aligncenter"><a href="media/d007d3ad.binary_mock.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2019/01/binary_mock.jpg" class="grouped_elements" rel="tc-fancybox-group25125"><img src="media/d007d3ad.binary_mock.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2019/01/binary_mock.jpg" alt="Les processeurs modernes ne comprenent pas nativement l&#039;american apparel" width="300" height="448" class="size-full wp-image-25162" /></a><p class="wp-caption-text">Les processeurs modernes ne comprenent pas nativement l&#8217;american apparel</p></div>
<p>Ou je peux lui appliquer une autre convention, et decider de lire ces octets comme si ils étaient le dump d&#8217;une structure C. Interprettons en Python ces octets comme un entier non signé en big-endian:</p>
<pre lang="python">     
>>> data = bytearray([0b1100001, 0b1100010, 0b1100011, 0b1100100])     
>>> import struct     
>>> struct.unpack('>I', data)     
(1633837924,)
</pre>
<p>Même suite de bits, mais selon la convention choisie, elle veut dire les lettres &#8220;abcd&#8221; ou le nombre &#8220;1633837924&#8221;. Et oui, comme il n&#8217;y a pas une infinité de combinaisons de 0 et de 1 qui tiennent dans un espace mémoire limité, différentes conventions vont utiliser les mêmes octets mais décider que ça veut dire quelque chose de différent.</p>
<p>En fait, même des conventions pour le même type usage ne veulent pas forcément dire la même chose. Par exemple, prenez l&#8217;octet:</p>
<p><code>11101001</code></p>
<p>Un octet somme toute sympathique, de bonne famille. Il ne paie pas de mine, mais c&#8217;est un membre utile de la société.</p>
<p>Et maintenant, quelqu&#8217;un vous donne un indice, il vous dit que cet octet représente&#8230; du texte.</p>
<p>Super !</p>
<p>Oui, mais du texte avec quelle convention ? Car les pays du monde entier ont créé leur propre convention pour représenter du texte.</p>
<p>Avec la convention &#8220;latin-1&#8221;, <a href="https://en.wikipedia.org/wiki/Windows-1252">utilisé par 0.7% de tous les sites Web du monde</a> ?</p>
<pre lang="python"> 
>>> bytearray([0b11101001]).decode('latin-1') 
'é' </pre>
<p>Avec la convention &#8220;cp850&#8221;, utilisé par la console DOS ?</p>
<pre lang="python"> 
>>> bytearray([0b11101001]).decode('cp850')
'Ú'
</pre>
<p>Vous voulez rire ? Le premier à remplacé presque partout le second parce qu&#8217;<a href="https://en.wikipedia.org/wiki/Code_page_850">ils contiennent les mêmes lettres</a>. Elles ne sont juste pas représentées par la même combinaison d&#8217;octets.</p>
<p>Et cet octet, que veut-il dire avec la convention &#8220;utf8&#8221;, qui est aujourd&#8217;hui le standard international recommandé pour représenter du texte ?</p>
<pre lang="python"> 
>>> bytearray([0b11101001]).decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 0: unexpected end of data </pre>
<p>Il n&#8217;a pas de correspondance. Cet octet n&#8217;est pas de l&#8217;utf8 valide.</p>
<p>Si vous voulez représenter ces lettres en utf8, il faut utiliser une convention différente, en utilisant non pas un seul octet, mais une séquence d&#8217;octets:</p>
<pre lang="python"> 
>>> list(map(bin, 'é'.encode('utf8')))
['0b11000011', '0b10101001']
>>> list(map(bin, 'Ú'.encode('utf8')))
['0b11000011', '0b10011010']
</pre>
<p>Vous pourriez croire que puisque le texte est particulièrement compliqué, c&#8217;est normal d&#8217;avoir des conventions qui divergent. Mais non, c&#8217;est juste la nature des conventions. Puisqu&#8217;elles sont arbitraires, l&#8217;une n&#8217;est pas plus &#8220;la vérité&#8221; qu&#8217;une autre. On retrouve la même chose avec les nombres:</p>
<pre lang="python">
>>> struct.unpack("h", bytearray([0b11101001, 0b11101001]))
(-5655,)
>>> struct.unpack("H", bytearray([0b11101001, 0b11101001])) 
(59881,)
</pre>
<p>La même suite d&#8217;octets peut représenter deux nombres totalement différents, selon que je décide de les lire comme des &#8220;short&#8221;, ou des &#8220;unsigned short&#8221;.</p>
<p>Et l&#8217;inverse est aussi vrai.</p>
<p>Ben oui, si quelque chose peut être interprété de plusieurs façons, on a aussi le fait que deux représentations <em>différentes</em> peuvent être interprétées &#8230; pour aboutir au même résultat.</p>
<p>Par exemple, le nombre des doigts de ma main peut être représenté de plein de façons différentes:</p>
<ul>
<li>         <strong>décimal</strong>: 5     </li>
<li>         <strong>français écrit</strong>: cinq     </li>
<li>         <strong>chiffre latin</strong>: V     </li>
<li>         <strong>anglais écrit</strong>: five     </li>
<li>         <strong>espagnol écrit</strong>: cinco     </li>
<li>         <strong>base deux</strong>: 101     </li>
<li>         <strong>structure C d&#8217;un signed short en little-endian avec Python</strong>: bytearray([0b101, 0b0])     </li>
</ul>
<p>Que de manières différentes, pour le même concept ! En plus, il y a confusion possible: V est une lettre également. cinq, five et cinco utilisent le même alphabet, mais pas les mêmes symboles spécifiques, pour représenter la même chose. Et le plus confusionant, 101 est une représentation binaire, mais <code>bytearray([0b101, 0b0])</code> aussi.</p>
<p>Bref, voilà toute la complexité de la différence entre la donnée, un concept abstrait qui n&#8217;existe pas, et sa représentation, une convention humaine concrète qui nous permet de communiquer entre nous.</p>
<p>Donc, pour lire &#8220;du binaire&#8221;, ou faire n&#8217;importe quoi en informatique, il faut connaitre la convention utilisée. Mais pas juste en informatique: pour lire le journal, il faut connaitre la convention des symboles imprimés sur les pages, pour conduire sans se faire tuer, il faut connaitre la convention des panneaux, et pour parler, il faut connaitre la convention de la compression des molécules d&#8217;air émise par l&#8217;appareil buccal et respiratoire d&#8217;un individu qui vient rencontrer votre système auditif.</p>
<p>Vous êtes un être très conventionnel au fond.</p>
<p>Évidemment on trouve la même chose en Python. Par exemple vous pouvez utiliser plusieurs conventions pour demander à Python de créer le même nombre en mémoire:</p>
<pre lang="python">
>>> 245 # base 10
245
>>> 0xF5 # hexadecimal
245
>>> 0b11110101 # binaire
245
>>> 245 == 0xF5 == 0b11110101
True     
>>> type(245)     
<class 'int'>     
>>> type(0xF5)     
<class 'int'>     
>>> type(0b11110101)     
<class 'int'> </pre>
<p>Inversement, <code>"1"</code> et <code>1</code> paraissent similaire, mais ils ont différents buts. Le premier est un outil destiné à l&#8217;affichage, qui matérialise le caractère représentant le chiffre arabe après le zéro. Il est stocké en interne avec une séquence d&#8217;octets similaire à:</p>
<pre lang="python">
>>> bin(ord("1"))
'0b110001'
</pre>
<p>Tandis que que le second est un outil fait pour faire des calculs avec la plus petite valeur positive entière non nulle. Il est stocké en interne avec une séquence d&#8217;octets similaire à:</p>
<pre lang="python">
>>> list(map(bin, struct.pack('l', 1)))
['0b1', '0b0', '0b0', '0b0', '0b0', '0b0', '0b0', '0b0']
</pre>
<p>Je simplifie bien entendu, en vérité la representation interne des nombres et du texte en Python est plus complexe que cela, et dépend de l&#8217;implémentation choisie, du type de processeur, de la taille de la donnée et de votre configuration.</p>
<h2>
Retour sur le type bytes </h2>
<p>J&#8217;ai soigneusement évité d&#8217;utiliser le type <code>bytes</code> durant cette démonstration, le remplaçant techniquement inutilement (mais pédagogiquement brillamment, car je suis génial) par <code>bytearray</code>.</p>
<p>En effet, toute cette leçon est là pour arriver à la conclusion que <code>bytes</code> ne représente pas du texte, mais si je vous avais montré tout ça avec lui, voilà qui vous aurait interloqué:</p>
<pre lang="python">     
>>> bytes([0b1100001, 0b1100010, 0b1100011, 0b1100100])     
b'abcd' </pre>
<p>&#8220;Heu, mais c&#8217;est du texte !&#8221; me dirait alors un lecteur ayant diagonalisé l&#8217;article.</p>
<p>Mais bien entendu que non.</p>
<p><code>bytes</code> ne présente pas du texte, c&#8217;est une structure de données dont le but est de permettre de manipuler une séquence d&#8217;octets ordonnée, et ce manuellement. N&#8217;importe laquelle.</p>
<p>Or, il se trouve que beaucoup de langages de programmation représentent le texte comme un array d&#8217;octets, et y attachent quelques opérations de manipulation. C&#8217;est le cas du C, ou de Python 2 par exemple. Les gens ayant eu cette expérience pensent donc que <code>b'abcd'</code> représente du texte, allant parfois jusqu&#8217;à aller lui donner l&#8217;appellation de &#8220;byte string&#8221;.</p>
<p>Il n&#8217;existe rien de tel en Python 3.</p>
<p>En Python 3, vous avez deux types pour manipuler des séquences d&#8217;octets: <code>bytes</code> et <code>bytearray</code>. Ils sont équivalents, à ceci près que <code>bytes</code> est non mutable (non modifiable) alors que <code>bytearray</code> est mutable (modifiable).</p>
<p>Ces types peuvent contenir n&#8217;importe quels octets, et nous avons vu ensemble qu&#8217;une même séquence d&#8217;octets pouvait être interprétée différemment selon la convention choisie pour la lire. Évidemment il est préférable de la lire avec la même convention qui a été utilisée pour la produire, sans quoi on ne comprendra pas ce que le producteur de la donnée à voulu dire.</p>
<p>Sauf que&#8230;</p>
<p>Beaucoup d&#8217;outils en informatique utilisent les conventions ASCII et hexadécimale pour symboliser les valeurs des octets. Si vous lancez <a href="https://www.wireshark.org/docs/wsug_html_chunked/ChapterIntroduction.html#ChIntroFeatures">Wireshark</a> pour regarder les paquets d&#8217;un protocole réseau ou si vous ouvrez un PNG avec <code>xxd</code>, on va vous représenter le contenu avec un mélange de ces conventions. </p>
<p>Pour des raisons pratiques, Python fait donc la même chose, et permet ainsi de visualiser (ou produire) le type <code>bytes</code> à l&#8217;aide d&#8217;une notation ASCII:</p>
<pre lang="python">    
>>> print(b'abcd'.decode('ascii'))     
abcd     
>>> struct.unpack('>I', b'abcd')     
(1633837924,)
</pre>
<p>Ou d&#8217;une notation héxa (ironiquement, l&#8217;héxa est representé par une combinaison de caractères ASCII \o/) si les valeurs ne tiennent pas dans la table ASCII:</p>
<pre lang="python">     
>>> "é".encode('utf8')  # hexa C3 A9   
b'\xc3\xa9'     
>>> struct.unpack('h', b'\xc3\xa9')    
(-22077,)
</pre>
<p>Donc <code>bytes</code>, bien qu&#8217;il puisse contenir des octets interprétables comme du texte, n&#8217;est pas particulièrement fait pour manipuler du texte. Il peut contenir n&#8217;importe quoi. Mais pour des raisons pratiques, sa représentation dans le terminal est faite avec une convention familière. Après tout, il faut bien l&#8217;écrire en quelque chose pour l&#8217;affiquer à l&#8217;écran.</p>
<p>Si on veut manipuler du texte en Python 3, il faut utiliser le type <code>str</code>, qui est l&#8217;outil spécialisé dans la representation et la manipulation textuelle. Si vous savez qu&#8217;un type <code>bytes</code> contient des octets qui representent du texte, alors utilisez la méthode <code>décode()</code> avec la bonne convention (appelée &#8220;charset&#8221;), pour récupérer un <code>str</code>:</p>
<pre lang="python">     
>>> print(b'P\xc3\xa8re No\xc3\xabl'.decode('utf8'))
Père Noël </pre>
<p>On a <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/ ">un très bon article sur l&#8217;encoding en Python</a> sur le blog, d&#8217;ailleurs.</p>
<p>Toute cela n&#8217;était bien entendu pas vrai en Python 2. En Python 2, le type <code>str</code> était un array d&#8217;octets, rendant tout cela bien confus, et amenant à plein d&#8217;erreurs. L&#8217;introduction lors de la version 2.0 de l&#8217;objet <code>unicode</code> pour pallier le problème, bien que très utile, n&#8217;a fait que rajouter à l&#8217;incomprehension des nouveaux venus.</p>
<p>Or le monde extérieur, lui, n&#8217;a pas d&#8217;abstraction pour le texte. Faire des abstractions, c&#8217;est le rôle du langage de programmation. Si vous écrivez dans un terminal, ou lisez depuis un terminal, un nom de fichier, le contenu d&#8217;une base de données, une requête AJAX, etc., ce sont évidemment des octets qui sont échangés, et il vous faut la bonne convention pour faire partie de la discussion.</p>
<p>Le type bas niveau <code>bytes</code> est un outil qui sert donc à communiquer avec le monde extérieur, tandis que les types haut niveau (<code>str</code>, <code>int</code>, <code>list</code>, etc.) sont des outils qui font l&#8217;abstraction de ces conventions, pour vous permettre de manipuler confortablement un concept général (du texte, un nombre, une collection ordonnée) à l&#8217;interieur des murs de votre programme.</p>


feed_id: http://sametmax.com/?p=25193
title: Stack Python en 2019
uri: Stack-Python-en-2019
url: http://sametmax.com/stack-python-en-2019/
content:
<p>Suite au très bon billet <a href="https://bersace.cae.li/conseils-python-2019.html">Débuter avec Python en 2019</a>, je me suis dit qu&#8217;il serait bon d&#8217;en rajouter une couche.</p>
<p>Après toutes ces années, qu&#8217;est-ce que j&#8217;utilise pour mes projets Python ?</p>
<h2>
    D&#8217;abord, Python 3.6, partout<br />
</h2>
<p>Pas la 3.5. Pas la 3.7.</p>
<p>La raison est que la 3.6 est un millésime exceptionnel, dans laquelle culminent des années de fixes et goodies. Malgré celà, sortie fin 2016, elle est facile à installer: ça prend quelques minutes <a href="https://cjsawer.whitewillow.co.uk/2018/08/29/epel-python-3-6-with-pip-on-centos-7/">sur même une centos 7 via les EPEL</a>, ou <a href="https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
">sur une ubuntu 16.04 en utilisant le ppa deadsnake</a>.</p>
<p>La 3.7 n&#8217;est non seulement pas aussi aisée à déployer, mais elle ne contient pas encore autant de correctifs, et surtout <a href="http://sametmax.com/la-debacle-de-async-en-3-7/#comment-197554">fige les mots clés async / await</a>, créant des surprises. J&#8217;admets volontiers que <code>breakpoint()</code>, les dataclasses et <code>asyncio.run()</code> sont très tentants, mais je peux vivre sans.</p>
<p>Donc Python 3.6.</p>
<p><em>(P.S: django et numpy droppent le support de la 3.4)</em></p>
<h2>
    Pour déployer, pex et nuikta<br />
</h2>
<p>Quand j&#8217;ai scripts rapides mais pleins de dépendances , fini les virtualenvs et pip install en prod. Je package tout avec <a href="https://github.com/pantsbuild/pex">pex</a>. Un fichier <code>.pex</code> est un format conçu par twitter l&#8217;équivalent d&#8217;un <code>.war</code>, que <a href="https://www.youtube.com/watch?v=NmpnGhRwsu0">la présentation de Brian Wickman</a> expliquera mieux que moi.</p>
<p>Mais en gros, en très gros, c&#8217;est un zip qui contient tout le virtualenv. On fait <code>python mon_projet.pex</code> et ça lance tout. Pas besoin de déploiement compliqué. <code>scp</code>, et c&#8217;est prêt. Je ne le recommande pas pour un gros projet web par contre. Mais pex rend le scripting Python merveilleux, et presque trop facile: plus besoin de s&#8217;interdire une dépendance par peur que le serveur ne l&#8217;a pas, ou par flemme. Du coup, même le script le plus simple à la puissance de feu de tout pypi, et ça m&#8217;a permis de faire des one-shots très complexes en deux coups de cuillères à pot.</p>
<p>Quand je dois livrer un programme chez un client qui ne soit pas Web, je compile tout avec <a href="http://nuitka.net/">nuitka</a>. Je me fends même parfois d&#8217;un installeur <a href="https://nsis.sourceforge.io/">nsis</a> au besoin. Demander à autrui d&#8217;installer la VM est source de beaucoup de problèmes, et Python est un détail d&#8217;implémentation pour beaucoup d&#8217;utilisateurs de toute façon.</p>
<h2>
    Gestion de projet: pew et setup.cfg<br />
</h2>
<p>J&#8217;aime <a href="https://github.com/sdispater/poetry">poetry</a>, mais la compatibilité avec setuptools est importante à mes yeux. Tout l&#8217;écosystème supporte setuptools, tout est bien testé, c&#8217;est robuste et sans surprise. J&#8217;attendrais que poetry soit stable, testé, bien intégré et surporté. Évidemment, il faudra que <code>pyproject.toml</code> soit suffisamment mature également, et vu l&#8217;usage de sections custo pour tous les outils qui l&#8217;utilisent, on en est encore loin.</p>
<p><a href="http://sametmax.com/mieux-que-python-virtualenvwrapper-pew/">pew</a> est très basique, mais il ne s&#8217;occupe que du virtualenv, laissant la gestion de mon projet à mes soins. Il est rapide, et sans chichi, de plus personne dans mon équipe n&#8217;a besoin de savoir que je l&#8217;utilise.</p>
<p>Après quelques essais, j&#8217;ai laissé tomber pipenv, qui a trop de problèmes, et dont l&#8217;auteur met des années avant d&#8217;entendre raison sur des choses essentielles, sur lesquelles il revient par ailleurs sans mine de repenti. Ça n&#8217;en retire rien à Kenneth Reth le mérite des ses travaux, mais j&#8217;ai des deadlines.</p>
<h2>
    Outillage<br />
</h2>
<p>À moins d&#8217;avoir été sourd et aveugle, vous avez du noter un certain engouement de la communauté pour <a href="http://sametmax.com/once-you-go-black-you-never-go-back/">black</a>, que je vous ai déjà dis avoir adopté.</p>
<p>Les conséquences sont multiples sur la stack: j&#8217;ai viré <a href="https://pypi.org/project/flake8/">flake8</a>, et j&#8217;ai allégé de nombreuses règles ma configuration <a href="http://pylint.pycqa.org/en/latest/">pylint</a>, qui est du coup mon seul linter. Faudrait que je fasse un article dessus d&#8217;ailleurs.</p>
<p><a href="http://mypy-lang.org/">Mypy</a> étant maintenant stable et utilisable, je l&#8217;active par défaut. Ça ne veut pas dire que j&#8217;annote tout mon code. Parfois je n&#8217;annote rien. Parfois juste quelques fonctions. L&#8217;énorme avantage de mypy réside dans le fait que son utilisation est parfaitement progressive, et s&#8217;adapte à l&#8217;engagement et l&#8217;effort que vous voulez y mettre.date mypy est une des rares choses que j&#8217;upgrade à tout bout de champ, car chaque update amène une vraie qualité de vie en plus.</p>
<p>J&#8217;intègre tout ça dans mon éditeur, et en l&#8217;occurence <a href="http://sametmax.com/je-fais-mon-coming-out/">VSCode</a> rend l&#8217;opération très facile.</p>
<p>Pour le lanceur de tests, je reste sur pytest, pour des raisons <a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/">déjà exposées</a>. Honnêtement je ne connais pas de bonnes raisons de ne pas utiliser pytest. J&#8217;utilise <a href="http://sametmax.com/generer-des-donnees-factices-avec-faker/">faker</a> pour générer des fausses données de test. Je n&#8217;arrive toujours pas à utiliser <a href="https://hypothesis.readthedocs.io/en/latest/">hypothesis</a>. J&#8217;essaye, mais je n&#8217;arrive jamais à l&#8217;appliquer sur autre chose qu&#8217;un exemple joujou. J&#8217;espère y arriver un jour, car je suis certain que c&#8217;est excellent.</p>
<p>Pour lancer tout ce bordel, j&#8217;utilise <a href="https://tox.readthedocs.io/en/latest/">tox</a>, mais je ne l&#8217;utilise pas sur tous mes projets: seulement les gros avec certaines exigences.</p>
<p>Je n&#8217;ai pas de template de projet type. J&#8217;ai beaucoup lorgné depuis des années du côté de <a href="http://sametmax.com/templates-de-projet-avec-cookiecutter/">cookiecutter</a>, je n&#8217;arrive pas à me motiver à l&#8217;utiliser sérieusement.</p>
<p>Enfin, j&#8217;installe toujours <a href="https://jupyter.org/">jupyter</a> pour tester vite fait mon code, bien que j&#8217;utilise plus la console que le notebook. Et <a href="http://www.sphinx-doc.org/en/master/">sphinx</a> pour la doc.</p>
<h2>
    Frameworks Web<br />
</h2>
<p><a href="https://www.djangoproject.com">Django</a> (souvent avec <a href="https://www.django-rest-framework.org/">django-rest-framework</a>).</p>
<p>J&#8217;ai parfois des clients qui exigent <a href="http://flask.pocoo.org/">flask</a>, et donc je fais du flask. C&#8217;est toujours à regret.</p>
<p>Il n&#8217;a rien que flask me permette que je ne puisse faire avec Django, mais il y a une tonne de trucs à réimplementer à la main à chaque fois. À documenter. À tester. Tout ça pour changer de projet flask, et tomber sur un nouveau loustic qui a fait les trucs à sa sauce et tout recommencer.</p>
<p>Les projets flask ne sont bien faits que par ceux qui savent déjà très bien mener un projet Web, ce qui n&#8217;est pas la majorité des gens qui l&#8217;utilisent: en effet, il attire les utilisateurs par la simplificité de son API, et leur donne l&#8217;illusion d&#8217;être à la hauteur.</p>
<p>flask reste un excellent produit pour l&#8217;éducation, ou pour un petit projet vite fait, ce pour  quoi je le choisis avec plaisir. Mais la majorité des projets flasks sur lesquels j&#8217;ai travaillé n&#8217;ont guère le niveau de qualité qu&#8217;on rencontre en moyenne dans les projets Python. C&#8217;est qu&#8217;on s&#8217;habitue, à force.</p>
<p>J&#8217;essaye aussi d&#8217;aimer <a href="https://www.sqlalchemy.org/">SQLALchemy</a>, dont je reconnais la flexibilité et la puissance. Mais son ergonomie est pénible, et la gestion des sessions suffisamment tortueuse pour se tirer une balle dans le pied si on cligne trop des yeux. Si j&#8217;ai des problèmes de perfs, je fais du SQL à la main de toute façon et j&#8217;utilise du cache en masse. Je reste donc sur SQLA seulement si flask, ou hors Web. Et encore, des fois je <a href="http://docs.peewee-orm.com/en/latest/peewee/quickstart.html#quickstart">peeweese</a>.</p>
<p>L&#8217;ORM de Django est une aberration en bien des points, sauf un seul. Il est éminemment pratique. Et je sais jusqu&#8217;où je peux le pousser: loin, très loin. Max va se gausser en lisant ces lignes, mais je me lasse de la beauté du code et de la pureté (ta gueule mec, arrête sourire, je te vois).</p>
<p>Bref, Django pour les seniors. Django pour les juniors, même si ça prendra plus de temps que flask, mais au moins le framework leur évitera de faire de la merde comme au temps de PHP à la main.</p>
<p>Question async, j&#8217;utilise <a href="https://aiohttp.readthedocs.io">aiohttp</a> mais aussi fais du <a href="https://docs.python.org/3/library/asyncio.html">asyncio</a> à là main, <a href="http://sametmax.com/go-to-in-asyncio-considered-harmful/">en faisant bien attention aux goto</a>.</p>
<p>Non, je n&#8217;utilise pas les trucs du genre sanic, growler, vibora, quart, etc. Si ils sont toujours activement développés dans 3 ans, on en reparle.</p>
<p>Bonne nouvelle ceci dit, la doc d&#8217;asyncio est enfin potable, si vous voulez vous y mettre. Mais ça mérite quand même un article.</p>
<p>Ceci dit, les occasions de faire de l&#8217;asyncio sont rares. REST reste (hu hu) quand même l&#8217;option reine, HTTP2 peut se déployer via proxy et les threads assurent le plus souvent des perfs suffisantes. Pour être parfaitement honnête, j&#8217;utilise plus asyncio pour des scripts, daemon, et autres tâches de fond :)</p>
<p>En parlant de tâche de fond, je reste sur du <a href="http://sametmax.com/files-de-taches-et-taches-recurrentes-avec-celery/">celery</a>, surtout depuis que je sais qu&#8217;on <a href="https://www.distributedpython.com/2018/07/03/simple-celery-setup/">peut l&#8217;utiliser avec presque zero config</a>. C&#8217;est le moins pire des systèmes. De toute façon j&#8217;ai presque toujours un redis sous la main, c&#8217;est bien trop facile et pratique pour s&#8217;en passer.</p>
<p>J&#8217;ai pas encore mis en prod django <a href="https://channels.readthedocs.io/en/latest/">channels</a>, ou <a href="https://github.com/slank/awsgi">aWSGI</a>, mais je ne suis pas du tout convaincu par ces solutions, donc j&#8217;attends de voir.</p>
<p>J&#8217;ai eu l&#8217;occasion d&#8217;utiliser <a href="http://sametmax.com/crossbar-le-futur-des-applications-web-python/">crossbar</a> un peu plus. L&#8217;outils est toujours excellent, mais l&#8217;API a changé sans pour autant s&#8217;améliorer. Ils se recroquevillent dans l&#8217;illusion qu&#8217;un produit spécialisé dans l&#8217;IoT est une bonne stratégie, mais c&#8217;est une voie de garage à mes yeux. Le vrai potentiel est dans le Web. Je me fais à l&#8217;idée que le projet n&#8217;attendra jamais son potentiel tant que personne n&#8217;écrit une surcouche, et que ce ne sera pas tavendo qui le fera.</p>
<h2>
    Libs<br />
</h2>
<p>Les libs changent constamment, partant et venant selon la nécessité des projets. Au mieux puis-je vous dire ce que j&#8217;irais chercher si j&#8217;avais cette problématique.</p>
<p>Dates: <a href="https://pendulum.eustace.io/">pendulum</a>.</p>
<p>Validation de données: <a href="https://marshmallow.readthedocs.io/en/3.0/">marshmallow</a>.</p>
<p>cli: <a href="https://click.palletsprojects.com/en/7.x/">click</a>. Ça me fait mal de le dire, car je suis pas fan du style des APIs d&#8217;Armin (l&#8217;objet <code>request</code> global de flask, sérieux&#8230;), mais quand il fait un truc, on est sûr que ça marche. J&#8217;ai eu trop de limitations avec les alternatives.</p>
<p>Gestion du pognon: <a href="https://pypi.org/project/money/">money</a>.</p>
<p>Lib graphique: <a href="https://wxpython.org/">wxPython</a>. Je fais du QT sur demande client, mais c&#8217;est trop gros pour des projets de moyenne taille.</p>
<p>Encoding: toujours <a href="https://pypi.org/project/chardet/">chardet</a> et <a href="https://pypi.org/project/Unidecode/">unidecode</a>.</p>
<p>Manipulation d&#8217;images: <a href="https://pillow.readthedocs.io">pillow</a>.</p>
<p>Calculs numériques: <a href="http://www.numpy.org/">numpy</a>. À mon niveau je n&#8217;ai jamais besoin de scipy ou pandas.</p>
<p>Pour le parsing de conf je fais de plus en plus de toml, mais j&#8217;ai pytoml est pas terrible. Je vous ferai un retour sur <a href="https://github.com/jumpscale7/python-consistent-toml">contoml</a> qui, si tout se passe bien, devrait être mon futur default.</p>
<p>Pour convertir du code Python 2 vers Python 3, <a href="https://pypi.org/project/future/">python future</a> et <a href="https://pypi.org/project/backports/">backport</a>.</p>
<p>Pour faire du templating, <a href="http://jinja.pocoo.org/">jinja2</a>.</p>
<p>Pour l&#8217;internationalisation, <a href="http://babel.pocoo.org/en/latest/">babel</a>.</p>
<h2>
    Hors de Python<br />
</h2>
<p>Git. <a href="http://sametmax.com/vue-jlavais-pas-vu/">Vue</a>. Webpack. Ubuntu.</p>
<p>J&#8217;évite docker comma la peste, même si certains clients le veulent à tout prix. Je fais du react, généralement sous la torture.</p>
<p>Pas grand-chose à dire de plus.</p>
<p>Ah si, j&#8217;ai laissé tombé zsh et fish pour revenir à bash. Le ROI me convient pas.</p>


feed_id: http://sametmax.com/?p=25303
title: Lancer correctement python et ses commandes cousines
uri: Lancer-correctement-python-et-ses-commandes-cousines-Recently-updat
url: https://sametmax.com/lancer-correctement-python-et-ses-commandes-cousines/
content:
<p>Si j&#8217;avais su, j&#8217;aurais écrit cet article il y a 5 ans. Je pense que tellement de monde aurait évité des heures de frustration. Mais ça prend du temps de réaliser que des choses qui vous paraissent simples sont des obstacles pour d&#8217;autres.</p>
<p>Mieux vaut tard que jamais j&#8217;imagine.</p>
<p>Dans cet article, on va voir comment lancer <code>python</code> depuis la ligne de commande, ainsi que les commandes qui lui sont liées: pip, venv, etc.</p>
<h2>Sous Windows</h2>
<p>Vous avez installé Python, c&#8217;est certain. Vous lisez votre premier tuto, qui vous dit de lancer <code>cmd.exe</code>, et de taper <code>python</code>, mais impossible de le faire marcher. Des messages du genre <code>‘python’ is not recognized as an internal or external command</code> apparaissent. Ou alors le mauvais Python se lance.</p>
<p>Déjà, premièrement, désinstallez Python, et réinstallez-le (en utilisant l&#8217;installeur officiel si possible), mais sur la toute première fenêtre de l&#8217;installeur, vérifiez bien que la case &#8220;Add Python to PATH&#8221; (ou son équivalent français) qui est tout en bas est cochée. Sans cela, le dossier d&#8217;installation de Python ne sera pas trouvable par le shell au moment de taper la commande. Je sais, ça devrait être coché par défaut. J&#8217;ai signalé ça plusieurs fois sur la mailing-list, et ils n&#8217;en ont rien à foutre.</p>
<div id="attachment_25314" style="width: 723px" class="wp-caption aligncenter"><a href="media/2cec24dd.python37_win_installer.png" data-original-source="http://sametmax.com/wp-content/uploads/2019/06/python37_win_installer.png" class="grouped_elements" rel="tc-fancybox-group25303"><img src="media/2cec24dd.python37_win_installer.png" data-original-source="http://sametmax.com/wp-content/uploads/2019/06/python37_win_installer.png" alt="Le clitoris de l&#039;installation de Python" width="713" height="455" class="size-full wp-image-25314" /></a><p class="wp-caption-text">Le clitoris de l&#8217;installation de Python</p></div>
<p>Alternativement, si vous ne voulez pas désinstaller Python, ou si vous n&#8217;utilisez pas l&#8217;installeur de Python standard, cherchez le dossier où vous avez installé python. C&#8217;est un dossier qui doit contenir <code>python.exe</code> et un dossier appelé <code>Scripts</code>. Très souvent on le trouve à <code>C:\users\[votre nom d'utilisateur]\Local Settings\Application Data\Programs\Python\Python36</code>. <a href="http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/">Ajoutez ce chemin dans le sys PATH</a>, ainsi le chemin vers le sous-dossier <code>Scripts</code>.</p>
<p><strong>Redémarrer votre console</strong>. Vous devriez au moins pouvoir taper <code>python -v</code>.</p>
<p>Maintenant, sachez que vous ne devriez pas taper la commande <code>python</code>.</p>
<p>Whaaaaaaaaaaaaat ?</p>
<p>Vous entends-je me hurler suavement à l&#8217;oreille.</p>
<p>Non. Sous Windows, vous devriez utiliser la commande <code>py -X.Y</code>. La commande <code>py</code> permet en effet de spécifier la version de Python à lancer. Par exemple <code>py -2.7</code> pour lancer Python 2.7, ou <code>py -3.6</code> pour lancer Python 3.6, s’ils sont installés sur la machine, bien entendu.</p>
<p>Pourquoi utiliser la commande <code>py</code> ? Et bien parce que sinon, <code>python</code> lancera le premier <code>python.exe</code> qu&#8217;il trouve. Si vous avez plusieurs versions de Python installées sur votre machine, ce qui est souvent le cas sur les machines de dev, des fois à son insu, vous allez avoir des problèmes.</p>
<p>En fait, quand vous lisez un tutoriel sur Python, si vous lisez quelque part &#8220;tapez python&#8221;, remplacez-le mentalement par &#8220;tapez py -X.Y&#8221;. La commande marche strictement pareil que la commande <code>python</code> traditionnelle. Elle prend les mêmes arguments, et lance le shell de la même façon.</p>
<p>Aussi, rien à voir, mais n&#8217;utilisez pas les terminaux de <code>cmd.exe</code> ou <code>powershell.exe</code>. Ils sont à chier. Prenez le temps de télécharger <a href="https://cmder.net/">cmder</a>, et si vous le pouvez, faites le <a href="https://github.com/cmderdev/cmder">cmder.exe /REGISTER ALL</a> en admin tant que vous y êtes.</p>
<p>Aussi petite astuce bien pratique: si vous maintenez <kbd>shift</kbd> et que vous faites un clic droit dans l&#8217;explorateur de fichier ou sur le bureau, un menu contextuel différent de celui habituel s&#8217;ouvre. Il contient des actions fort utiles:</p>
<ul>
<li>&#8220;Ouvrir fenêtre de commande ici&#8221;, qui vous ouvrira la console, immédiatement dans le bon dossier.</li>
<li>&#8220;Copier en tant que chemin d&#8217;accès&#8221;, qui vous permettra de mettre le chemin de n&#8217;importe quel fichier dans le presse-papier.</li>
</ul>
<h2>Sous Unix (Max, Linux, etc)</h2>
<p>N&#8217;utilisez pas la commande <code>python</code>, mais utilisez une commande suffixée <code>pythonX.Y</code>. Par exemple, pour lancer Python 2.7, tapez <code>python2.7</code>, ou pour lancer Python 3.6, tapez <code>python3.6</code>. </p>
<p>En fait, quand vous lisez un tutoriel sur Python, si vous lisez quelque part &#8220;tapez python&#8221;, remplacez-le mentalement par &#8220;tapez pythonX.Y&#8221;. La commande marche strictement pareil que la commande <code>python</code> traditionnelle. Elle prend les mêmes arguments, et lance le shell de la même façon, mais comme on a souvent plusieurs versions de Python installées sur une machine (sans parfois même sans rendre compte), c&#8217;est important de le faire.</p>
<h2>Pour les linuxiens seulement</h2>
<p>Pip et virtualenv sont fournis quand on installe Python sous Mac et Windows, mais souvent pas sous Linux ! Assurez-vous de toujours les installer avec votre gestionnaire de paquet, et ce <strong>pour chaque version de Python que vous avez</strong>.</p>
<p>Exemple: <code>yum install python3.6-pip</code> ou <code>apt install python3.6-venv</code>.</p>
<h2>Tous OS confondus</h2>
<p>Quand vous utilisez une commande écrite en Python, mettez <code>python -m</code> devant. C&#8217;est un cheat code.</p>
<p>N&#8217;appelez-pas <code>pip</code>, mais <code>python -m pip</code>.</p>
<p>N&#8217;appelez-pas <code>venv</code>, mais <code>python -m venv</code>.</p>
<p>N&#8217;appelez-pas <code>black</code>, mais <code>python -m black</code>.</p>
<p>Si vous lisez dans un tutoriel &#8220;tapez pip install&#8221;, remplacez-le mentalement par &#8220;tapez python -m pip install&#8221;.</p>
<p><code>-m</code> ne marche pas avec toutes les commandes (<code>python -m jupyter console</code> a un bug, snif) car cela suppose que le développeur de la commande y a pensé, mais c&#8217;est le cas de la plupart des outils modernes. </p>
<p>Or <code>-m</code> va vous éviter tout un tas de problème de PATH, de droits et de version de Python.</p>
<p>Donc, si on combine tous les conseils, n&#8217;utilisez pas <code>pip</code>, mais <code>py -3.6 -m pip</code> ou <code>python3.6 -m pip</code>.</p>
<p>Je sais, c&#8217;est plus long a taper, mais ça va bien vous aider. </p>
<h2>pip install</h2>
<p>Certains outils doivent s&#8217;installer en global. On voit souvent des conseils comme faire un <code>sudo pip install</code> ou un <code>sudo easy_install</code>. C&#8217;est mal. Ceci va pourrir les paquets système de Python, et peut avoir des conséquences indésirables. Notez que parfois, rien ne marche, et je le fais quand même du coup.</p>
<p>Mais la plupart du temps, ce qu&#8217;il vous faut, c&#8217;est <code>--user</code>, suivi de <code>-m</code>. Par exemple, ne faites pas:</p>
<pre lang="bash"> 
sudo pip install black 
black mon_fichier.py </pre>
<p>Mais faites:</p>
<pre lang="bash"> 
python3.6 -m pip install black --user 
python3.6 -m black mon_fichier.py </pre>
<p>Notez le <code>--user</code>, ainsi que les deux usages de <code>-m</code>.</p>
<p>Ceci va installer black localement, pas au niveau du système. On s&#8217;assure qu&#8217;on n&#8217;utilise bien Python3.6, à l&#8217;installation et à l&#8217;usage de black. Et comme on n&#8217;utilise <code>-m</code>, on a pas à se demander si la commande <code>black</code> est bien sur le <code>PATH</code> (pas besoin de trifouiller son <code>.bashrc</code> ou le sys <code>PATH</code> de Windows.)</p>
<h2>Mais c&#8217;est trop chiant !</h2>
<p>Absolulement, c&#8217;est aussi pour cela qu&#8217;<a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">on utilise des environnements virtuels</a>.</p>
<p>Utilisez des virtualenvs. Abusez-en. Un virtualenv par projet. Un autre pour les tests rapidos. Un pour maman, un pour papa, et un pour le fun. Ils ne coûtent rien que quelques Mo sur votre disque dur, donc lâchez-vous.</p>
<p>Car dans un virtualenv, non seulement vous êtes isolés des autres installations de Python, mais en plus&#8230; tous les conseils ci-dessus ne sont plus nécessaires !</p>
<p>Vous pouvez taper juste <code>python</code> et juste <code>pip</code>, plus de <code>py</code>, plus de suffixes, plus de <code>-m</code> et <code>--user</code>. Joie !</p>
<p>Moralité: les rares fois où vous êtes hors virtualenv, suivez les conseils des autres parties de l&#8217;article (<code>py -3.6 -m pip install --user</code> ou <code>python3.6 -m pip install --user</code>). Et des que vous le pouvez, pouf, virtualenv, et tout va pour le mieux.</p>


feed_id: http://sametmax.com/?p=25357
title: Le blog ferme
uri: Le-blog-ferme-5-Recently-updated
url: http://sametmax.com/la-blog-ferme/
content:
<p>J&#8217;ai envie de passer à autre chose. Max ne s&#8217;en occupe plus depuis longtemps. Du coup je mets sametmax.com en berne. Vu le rythme de publication de 2019, ça ne fera pas une grosse différence de toute façon.</p>
<p>Évidemment, il restera en ligne, avec tout son contenu. <a href="https://0bin.net/">0bin.net</a> aussi. Rappelez-vous que vous pouvez télécharger tout le blog pour le consulter hors ligne avec un petit:</p>
<pre lang="bash">wget -m -k -p -c -E http://sametmax.com</pre>
<p>Max, pour le moment, veut bien maintenir à flot le <a href="http://multiboards.net/">multiboards</a> et a même fait un peu de modération sur <a href="http://indexerror.net/">indexerror.net</a> donc pour le moment, les services restent up.</p>
<p>J&#8217;avais déjà laissé tomber le reddit et le mastodont, mais le compte Twitter restait très actif. J&#8217;ai fait une demande de twitter pour télécharger tous les tweets pour avoir un historique. Je pense le mettre en lecture seule.</p>
<p>Ca a été un plaisir d&#8217;écrire les plus de 1000 articles de ce blog, avec la participation d&#8217;auteurs invités en prime, et les commentaires super sympas. Il y en a presque autant de pas publié, dont certains articles invités que je fais trainé depuis super longtemps. Désolé !</p>
<p>Même si Max n&#8217;a pas beaucoup écrit ces dernières années, c&#8217;est un pote en or et j&#8217;ai de la chance de l&#8217;avoir à mes côtés au quotidien. C&#8217;est vraiment hilarant d&#8217;aller à une conférence ou chez un client et d&#8217;entendre parler de nous: &#8220;tu connais sametmax ? &#8211; oui, très bon blog :) :) :)&#8221;.</p>
<p>Bonne pythonade à tous, et mettez un préservatif.</p>
<p>P.S: je rouvre les comments pour quelques jours. </p>


feed_id: https://sametmax.com/?p=26
title: Que sont les websockets et à quoi ca sert ?
uri: Que-sont-les-websockets-et-à-quoi-ca-sert
url: https://sametmax.com/quest-ce-que-les-websockets-et-a-quoi-ca-sert/
content:
Le protocole WebSocket vise à créer un canal de communication entièrement duplex, basé sur le socket TCP. Le Web a évolué. Nous sommes passés de Gopher à HTTP 1, puis 1.1. Nous avons également utilisé AJAX pour rafraîchir la page, sans avoir à tout recharger. Aujourd&#8217;hui, nous avons des applications qui peuvent faire des centaines [&#8230;]


feed_id: https://sametmax.com/?p=16
title: Comment utiliser les générateurs et les yield en Python ?
uri: Comment-utiliser-les-générateurs-et-les-yield-en-Python
url: https://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/
content:
Les générateurs sont une fonctionnalité étonnante de Python et constituent un élément essentiel de la compréhension du langage. Une fois que vous les aurez maîtrisés, vous ne pourrez plus vous en passer. Rappel sur les itérables Si vous lisez les éléments un par un dans un tableau, cela s&#8217;appelle une itération. lst = [1, 2, [&#8230;]


feed_id: https://sametmax.com/?p=13
title: Comment décompresser sous Linux en ligne de commande ?
uri: Comment-décompresser-sous-Linux-en-ligne-de-commande
url: https://sametmax.com/decompresser-sous-linux-en-ligne-de-comma-nde/
content:
Pour de nombreuses tâches informatiques et administratives, Linux est le système d&#8217;exploitation préféré par les utilisateurs avancés. Les administrateurs système et les développeurs sont particulièrement attirés par sa flexibilité, sa robustesse et sa sécurité. Une fonctionnalité très pratique de Linux est la capacité de décompresser des fichiers en ligne de commande. Dans cet article, nous [&#8230;]


feed_id: https://sametmax.com/?p=6
title: Qu’est-ce que Javascript et à quoi ça sert ?
uri: Qu-est-ce-que-Javascript-et-à-quoi-ça-sert
url: https://sametmax.com/quest-ce-que-javascript-et-a-quoi-ca-sert/
content:
La question parait bête, mais je me la suis posé il y a des années. Et personne n’avait écrit un article pour expliquer ça. Personne. C’était tellement évident. Cet article est pour toi, étudiant en info, commercial dans une boîte IT ou juste curieux qui trouve que l’article Wikipedia ne veut rien dire. Javascript Javascript est un [&#8230;]


feed_id: https://sametmax.com/?p=78
title: Python, meilleur nulle part, excellent partout
uri: Python-meilleur-nulle-part-excellent-partout
url: https://sametmax.com/python-meilleur-nul-part-excellent-partout/
content:
Article repris en hommage à l&#8217;ancien site web qui a tant apporté à la communauté dev francaise Je ne sais pas si vous l’aviez compris, mais j’aime bien Python. J’ai essayé de vous le cacher jusqu’ici, mais je sais que mon secret ne tiendra pas longtemps, alors j’avoues tout. Je n’aime pas Python parce que c’est [&#8230;]


feed_id: https://sametmax.com/?p=75
title: FizzBuzz en Python, qu’est ce que c’est ?
uri: FizzBuzz-en-Python-qu-est-ce-que-c-est
url: https://sametmax.com/fizzbuzz-en-python/
content:
Le FizzBuzz est un type de test qui a été rendu populaire par Imran Ghory et ayant pour but de gagner du temps dans l’embauche de développeurs. Son constat est alarmant : une grande majorité des gens qui venaient aux entretiens pour un poste de programmeur, diplôme / CV / beau discours à l’appui, ne savaient pas… [&#8230;]


feed_id: https://sametmax.com/?p=70
title: Files de tâches et tâches récurrentes avec Celery
uri: Files-de-tâches-et-tâches-récurrentes-avec-Celery
url: https://sametmax.com/files-de-taches-et-taches-recurrentes-avec-celery/
content:
Quand on a à traiter des choses bloquantes, avec des dépendances, des flux complexes ou des actions répétitives, créer des files d’attente peut se révéler très judicieux. Par exemple lancer la génération d’un gros zip sur le clic d’un utilisateur, télécharger plein fichiers en parallèle pour son site de cul, lancer des calculs sur plusieurs [&#8230;]


feed_id: https://sametmax.com/?p=66
title: La théorie de la salle de bain et (un tout petit peu de) Python
uri: La-théorie-de-la-salle-de-bain-et-(un-tout-petit-peu-de)-Python
url: https://sametmax.com/la-theorie-de-la-salle-de-bain-et-un-tout-petit-peu-de-python/
content:
Article repris de l&#8217;ancien site à titre d&#8217;hommage. Il y a quelques jours, j’ai tweeté une vidéo d’une heure de mauvaise qualité où l’on voyait un vieillard parler en anglais de la fonction exponentielle. Le tweet n’a pas eu de succès. Je me demande bien pourquoi. 🙂 C’est extrêmement fâcheux car cette vidéo est d’une importance [&#8230;]


feed_id: https://sametmax.com/?p=60
title: Quelques outils pour gérer les clés secrètes en Django
uri: Quelques-outils-pour-gérer-les-clés-secrètes-en-Django
url: https://sametmax.com/quelques-outils-pour-gerer-les-cles-secretes-en-django/
content:
Cet article est repris de l&#8217;archive et appartient à l&#8217;ancien propriétaire du site, il a été repris sur celui-ci dans une forme d&#8217;hommage On ne veut pas mettre sa SECRET_KEY en prod, et utiliser un service pour générer la clé, ça va deux minutes. Générer une clé secrète: import random import string &#160; def secret_key(size=50): pool [&#8230;]


feed_id: https://sametmax.com/?p=48
title: Pourquoi obliger le SSL par défaut est une bêtise
uri: Pourquoi-obliger-le-SSL-par-défaut-est-une-bêtise
url: https://sametmax.com/pourquoi-obliger-le-ssl-par-defaut-est-une-grosse-connerie/
content:
Chrome et Mozilla discutent de la possibilité de restreindre les fonctionnalités de leurs navigateurs sur les sites web qui n&#8217;utilisent pas le protocole SSL. Sur le papier, c&#8217;est posé avec de bonnes intentions : obliger les développeurs de sites à crypter la communication entre le serveur et le client. Cela offrira plus de sécurité aux [&#8230;]


feed_id: https://sametmax.com/?p=43
title: YAML, XML, JSON, CSV, INI… Qu’est-ce que c’est et à quoi ça sert ?
uri: YAML-XML-JSON-CSV-INI-Qu-est-ce-que-c-est-et-à-quoi-ça-se
url: https://sametmax.com/yaml-xml-json-csv-ini-quest-ce-que-cest-et-a-quoi-ca-sert/
content:
Cet article est une reprise de l&#8217;ancien contenu du site, les anciens propriétaires en sont donc les propriétaires, nous l&#8217;avons mis ici en tant qu&#8217;hommage. Que voilà de jolis acronymes ! Quand j’ai commencé la programmation, je les rencontrais partout sur le net. On en parlait comme si on parlait d’acheter du pain. Apparemment, c&#8217;était évident pour [&#8230;]


feed_id: https://sametmax.com/?p=40
title: La différence entre une offre d’emploi française et américaine
uri: La-différence-entre-une-offre-d-emploi-française-et-américaine
url: https://sametmax.com/la-difference-entre-une-offre-demploi-francaise-et-americaine/
content:
Cet article est une reprise de l’ancien contenu du site, les anciens propriétaires en sont donc les propriétaires, nous l’avons mis ici en tant qu’hommage. C&#8217;est la raison pour laquelle la plupart des meilleurs programmeurs que j&#8217;ai connus n&#8217;ont travaillé qu&#8217;avec des Américains pendant un certain temps : Offre française contre Offre américaine (surtout parce [&#8230;]


feed_id: https://sametmax.com/?p=33
title: Programmation par contrat avec assert
uri: 2022-12-12-Programmation-par-contrat-avec-assert
url: https://sametmax.com/programmation-par-contrat-avec-assert/
content:
Cet article est une reprise de l’ancien contenu du site, les anciens propriétaires en sont donc les propriétaires, nous l’avons mis ici en tant qu’hommage. Le mot-clé assert est un choix populaire en Python en raison de la bibliothèque pytest, que nous avons couverte dans notre section sur les tests unitaires. En dehors de ce [&#8230;]


feed_id: https://sametmax.com/?p=30
title: Retour sur la pénurie de dev
uri: Retour-sur-la-pénurie-de-dev
url: https://sametmax.com/retour-sur-la-penurie-de-devs/
content:
Cet article est une reprise de l’ancien contenu du site, les anciens propriétaires en sont donc les propriétaires, nous l’avons mis ici en tant qu’hommage. Autour de moi, nous recherchons plus de 50 développeurs Joomla Un bon ami m&#8217;a raconté une conversation qu&#8217;il a eue avec une de ses connaissances à Nantes. Nantes n&#8217;est pas [&#8230;]


feed_id: https://sametmax.com/?p=86
title: Ajouter un chemin à la variable d’environnement PATH sous Windows
uri: Ajouter-un-chemin-à-la-variable-d-environnement-PATH-sous-Windows
url: https://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/
content:
Cet article est une reprise de l&#8217;ancien contenu du site, nous n&#8217;en sommes donc pas propriétaires, il a été reposté en hommage à ce que Sam et Max a apporté à la communauté dév Il y a beaucoup de tutos qui demandent de simplement “ajouter le résultat au PATH”, mais assez peu expliquent pourquoi et ... <a title="Ajouter un chemin à la variable d’environnement PATH sous Windows" class="read-more" href="https://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/" aria-label="Plus sur Ajouter un chemin à la variable d’environnement PATH sous Windows">Lire plus</a>


feed_id: https://sametmax.com/?p=81
title: 5 choses à apprendre en priorité en Python
uri: 5-choses-à-apprendre-en-priorité-en-Python
url: https://sametmax.com/5-choses-a-apprendre-en-priorite-en-python/
content:
Quand on apprend un nouveau langage de programmation, on apprend d’abord les bases. Et pour la plupart des langages, elles sont communes : déclarer une variable, faire des conditions et des boucles, faire des fonctions, importer un code d’un autre fichier, etc. Ce qui va différencier le moment où vous savez programmer dans CE langage, [&#8230;]


feed_id: https://sametmax.com/?p=63
title: Crossbar, le futur des applications Web Python ?
uri: 2022-12-13-Crossbar-le-futur-des-applications-Web-Python
url: https://sametmax.com/crossbar-le-futur-des-applications-web-python/
content:
Précision : Cet article fait partie de l&#8217;ancien site et appartient donc à l&#8217;ancien propriétaire, nous avons décidé de le reposter en hommage à l&#8217;ancien site Je suis crossbar.io depuis quelque temps maintenant, et je suis vraiment très étonné de ne pas plus en entendre parler dans la communauté Python. Bon, en fait, à moitié étonné. D’un ... <a title="Crossbar, le futur des applications Web Python ?" class="read-more" href="https://sametmax.com/crossbar-le-futur-des-applications-web-python/" aria-label="Plus sur Crossbar, le futur des applications Web Python ?">Lire plus</a>


feed_id: https://sametmax.com/?p=95
title: Comment parser du HTML avec BeautifulSoup ?
uri: Comment-parser-du-HTML-avec-BeautifulSoup
url: https://sametmax.com/parser-du-html-avec-beautifulsoup/
content:
La programmation web implique souvent l&#8217;analyse et le traitement de documents HTML. Cette tâche peut être complexe et fastidieuse à réaliser manuellement. Heureusement, il existe des outils et des bibliothèques qui peuvent aider à cette tâche. L&#8217;un de ces outils est la bibliothèque Python appelée BeautifulSoup. Qu&#8217;est-ce que BeautifulSoup ? BeautifulSoup est une bibliothèque Python ... <a title="Comment parser du HTML avec BeautifulSoup ?" class="read-more" href="https://sametmax.com/parser-du-html-avec-beautifulsoup/" aria-label="Plus sur Comment parser du HTML avec BeautifulSoup ?">Lire plus</a>


feed_id: https://sametmax.com/?p=99
title: Comment optimiser MySQL en utilisant le Cache Query Cache Size ?
uri: Comment-optimiser-MySQL-en-utilisant-le-Cache-Query-Cache-Size
url: https://sametmax.com/optimiser-mysql-en-utilisant-le-cache-query_cache_size/
content:
MySQL est un système de gestion de base de données très populaire et largement utilisé. La mise en œuvre efficace de MySQL est essentielle pour les performances des applications Web. Il existe plusieurs méthodes et techniques pour optimiser MySQL, et une d&#8217;entre elles est le Cache Query Cache Size. L&#8217;utilisation de ce cache peut contribuer ... <a title="Comment optimiser MySQL en utilisant le Cache Query Cache Size ?" class="read-more" href="https://sametmax.com/optimiser-mysql-en-utilisant-le-cache-query_cache_size/" aria-label="Plus sur Comment optimiser MySQL en utilisant le Cache Query Cache Size ?">Lire plus</a>


feed_id: https://sametmax.com/?p=125
title: Qu’est-ce qu’un middleware Django ?
uri: Qu-est-ce-qu-un-middleware-Django
url: https://sametmax.com/quest-ce-quun-middleware-django/
content:
Le middleware Django est une technologie très puissante qui permet aux développeurs de créer des applications Web à l&#8217;aide du framework Django. Cet outil permet aux développeurs d&#8217;accéder à des données et à des fonctionnalités supplémentaires qu&#8217;ils ne pourraient pas atteindre sans cet outil. Le middleware Django est très populaire dans le monde du développement ... <a title="Qu&#8217;est-ce qu&#8217;un middleware Django ?" class="read-more" href="https://sametmax.com/quest-ce-quun-middleware-django/" aria-label="Plus sur Qu&#8217;est-ce qu&#8217;un middleware Django ?">Lire plus</a>


feed_id: https://sametmax.com/?p=106
title: Le fichier gitkeep, c’est quoi ?
uri: Le-fichier-gitkeep-c-est-quoi
url: https://sametmax.com/le-fichier-gitkeep/
content:
Le fichier .gitkeep est un fichier qui est présent dans un dépôt GitHub et qui n&#8217;a pas de contenu. Il est présent dans un dépôt pour permettre de créer un dossier vide dans un dépôt GitHub quand le dossier est créé localement sans aucun fichier. Le fichier .gitkeep est un fichier qui est créé par ... <a title="Le fichier gitkeep, c&#8217;est quoi ?" class="read-more" href="https://sametmax.com/le-fichier-gitkeep/" aria-label="Plus sur Le fichier gitkeep, c&#8217;est quoi ?">Lire plus</a>


feed_id: https://sametmax.com/?p=103
title: L’encoding en python
uri: L-encoding-en-python
url: https://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/
content:
Python est un langage de programmation extrêmement populaire pour le développement Web et d&#8217;applications. Il est riche en outils et en bibliothèques qui facilitent la programmation et permettent aux développeurs de créer des applications à la fois puissantes et robustes. Une des fonctionnalités importantes de Python est l&#8217;encoding. L&#8217;encoding est une technique qui convertit un ... <a title="L&#8217;encoding en python" class="read-more" href="https://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/" aria-label="Plus sur L&#8217;encoding en python">Lire plus</a>


feed_id: https://sametmax.com/?p=139
title: Écrire des logs en Python
uri: Écrire-des-logs-en-Python
url: https://sametmax.com/ecrire-des-logs-en-python/
content:
Cet article a été repris pour rendre hommage a SametMax et ce qu&#8217;ils ont apportés à la communauté dev française. Au lieu de mettre des&#160;print()&#160;partout qu’il va falloir retirer après et qui en plus ne servent à rien dans un processus daemonisé, utiliser les facilités de logging de Python peut se révéler un bon investissement. ... <a title="Écrire des logs en Python" class="read-more" href="https://sametmax.com/ecrire-des-logs-en-python/" aria-label="Plus sur Écrire des logs en Python">Lire plus</a>


feed_id: https://sametmax.com/?p=109
title: Git Stash, c’est quoi ?
uri: Git-Stash-c-est-quoi
url: https://sametmax.com/soyez-relax-faites-vous-un-petit-git-stash/
content:
Git Stash est un outil pratique pour les développeurs qui travaillent sur des projets complexes. Il permet d&#8217;enregistrer des modifications non commitées et de les réutiliser plus tard, ce qui facilite grandement le travail d&#8217;équipe. Git Stash permet également de maintenir une version cohérente des modifications effectuées par les développeurs et de les comparer rapidement ... <a title="Git Stash, c&#8217;est quoi ?" class="read-more" href="https://sametmax.com/soyez-relax-faites-vous-un-petit-git-stash/" aria-label="Plus sur Git Stash, c&#8217;est quoi ?">Lire plus</a>


feed_id: https://sametmax.com/?p=122
title: Pourquoi utiliser le self en python ?
uri: Pourquoi-utiliser-le-self-en-python
url: https://sametmax.com/pourquoi-self-en-python/
content:
Les connaisseurs de Python savent que le Self est un élément crucial pour comprendre la programmation objet en Python. Mais pour les nouveaux venus, le Self peut sembler un peu intimidant au premier abord. Dans cet article, nous allons examiner ce qu&#8217;est le Self et comment l&#8217;utiliser dans le code Python. Qu&#8217;est-ce que le Self ... <a title="Pourquoi utiliser le self en python ?" class="read-more" href="https://sametmax.com/pourquoi-self-en-python/" aria-label="Plus sur Pourquoi utiliser le self en python ?">Lire plus</a>


feed_id: https://sametmax.com/?p=112
title: La méthode strip des chaines en Python
uri: La-méthode-strip-des-chaines-en-Python
url: https://sametmax.com/le-piege-de-la-methode-strip-des-chaines-en-python/
content:
Python est un langage de programmation très populaire qui est utilisé dans le monde entier. Une des fonctionnalités de Python qui est très utile est la méthode strip(), qui permet de supprimer des caractères indésirables à l&#8217;extrémité d&#8217;une chaîne. Quel que soit le type de projet sur lequel vous travaillez, il est important d&#8217;être à ... <a title="La méthode strip des chaines en Python" class="read-more" href="https://sametmax.com/le-piege-de-la-methode-strip-des-chaines-en-python/" aria-label="Plus sur La méthode strip des chaines en Python">Lire plus</a>


feed_id: https://sametmax.com/?p=144
title: A quoi sert Ellipsis en Python ?
uri: A-quoi-sert-Ellipsis-en-Python
url: https://sametmax.com/a-quoi-sert-ellipsis-en-python/
content:
Cet article appartient à l&#8217;ancien propriétaire du site web, nous n&#8217;en sommes pas les créateurs et n&#8217;en tireront aucune rémunération. L&#8217;article est posté à titre d&#8217;hommage a Sametmax.com et ce qu&#8217;ils ont apportés à la communauté. A rien. Nan mais revenez, je déconnais. Mais, sérieusement, Ellipsis, à la base, ne sert à rien. Il existe, c’est ... <a title="A quoi sert Ellipsis en Python ?" class="read-more" href="https://sametmax.com/a-quoi-sert-ellipsis-en-python/" aria-label="Plus sur A quoi sert Ellipsis en Python ?">Lire plus</a>


feed_id: https://sametmax.com/?p=115
title: Les alternatives au do while en python
uri: Les-alternatives-au-do-while-en-python
url: https://sametmax.com/alternative-au-do-while-en-python/
content:
Il y a plusieurs façons de traiter des données en Python, et l&#8217;une des méthodes les plus populaires est le do while. Cet article explorera les alternatives à cette méthode et examinera leurs avantages et leurs inconvénients. Les développeurs trouveront ici un aperçu des différentes options disponibles et des critères à prendre en compte pour ... <a title="Les alternatives au do while en python" class="read-more" href="https://sametmax.com/alternative-au-do-while-en-python/" aria-label="Plus sur Les alternatives au do while en python">Lire plus</a>


feed_id: https://sametmax.com/?p=119
title: Pipenv : le gestionnaire d’environnement Python le plus facile à utiliser
uri: Pipenv-le-gestionnaire-d-environnement-Python-le-plus-facile-à-ut
url: https://sametmax.com/pipenv-solution-moderne-pour-remplacer-pip-et-virtualenv/
content:
Pipenv est un outil open source qui permet de gérer les dépendances et les environnements virtuels de votre projet Python. Il fournit des fonctionnalités avancées pour faciliter la gestion des dépendances et des environnements virtuels pour vos projets Python. En tant que gestionnaire d&#8217;environnement Python, Pipenv vous permet de gérer facilement vos dépendances et de ... <a title="Pipenv : le gestionnaire d&#8217;environnement Python le plus facile à utiliser" class="read-more" href="https://sametmax.com/pipenv-solution-moderne-pour-remplacer-pip-et-virtualenv/" aria-label="Plus sur Pipenv : le gestionnaire d&#8217;environnement Python le plus facile à utiliser">Lire plus</a>


feed_id: https://sametmax.com/?p=161
title: Le formatage des strings en long et en large
uri: Le-formatage-des-strings-en-long-et-en-large
url: https://sametmax.com/le-formatage-des-strings-en-long-et-en-large/
content:
Un problème qui se retrouve souvent, c’est le besoin d’afficher un message qui contient des valeurs de variables. Or, si en Python on privilégie généralement “il y a une seule manière de faire quelque chose”, cela ne s’applique malheureusement pas au formatage de chaînes qui a accumulé bien des outils au fil des années. TL;DR ... <a title="Le formatage des strings en long et en large" class="read-more" href="https://sametmax.com/le-formatage-des-strings-en-long-et-en-large/" aria-label="Plus sur Le formatage des strings en long et en large">Lire plus</a>


feed_id: https://sametmax.com/?p=157
title: Les docstrings en Python
uri: Les-docstrings-en-Python
url: https://sametmax.com/les-docstrings/
content:
Une des mes fonctionnalités favorites en Python est son mécanisme de documentation du code : les doctrings. En effet, je crois qu’il est très important de rendre simple les tâches over chiantes comme les tests unitaires ou la doc car moins il y a de frein à le faire, plus il y a de chances qu’on le ... <a title="Les docstrings en Python" class="read-more" href="https://sametmax.com/les-docstrings/" aria-label="Plus sur Les docstrings en Python">Lire plus</a>


feed_id: https://sametmax.com/?p=154
title: Heartbleed, qu’est ce que c’est
uri: Heartbleed-qu-est-ce-que-c-est
url: https://sametmax.com/heartbleed-une-semaine-plus-tard/
content:
Il y a eu pas mal d’infos sur le sujet, généralement assez technique et en anglais, aussi je vous fais un petit résumé de la crise. Le 8 avril dernier, une faille dans le logiciel OpenSSL, surnommée Heartbleed, a été rendue publique. OpenSSL est le logiciel le plus utilisé au monde pour chiffrer les communications entre le ... <a title="Heartbleed, qu&#8217;est ce que c&#8217;est" class="read-more" href="https://sametmax.com/heartbleed-une-semaine-plus-tard/" aria-label="Plus sur Heartbleed, qu&#8217;est ce que c&#8217;est">Lire plus</a>


feed_id: https://sametmax.com/?p=150
title: L’environnement virtuel Python : venv, virtualenv et virtualenvwrapper
uri: L-environnement-virtuel-Python-venv-virtualenv-et-virtualenvwrapp
url: https://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/
content:
Quand on commence à beaucoup programmer, on accumule rapidement plusieurs projets en cours de développement sur sa machine. Certains vieux, certains récents, qui utilisent tous des bibliothèques similaires, mais pas forcément de mêmes versions. Ou parfois des bibliothèques incompatibles. Parfois même, des versions différentes de Python : Python 2.6, 2.7, 3.2 ? Et c’est sans compter ... <a title="L&#8217;environnement virtuel Python : venv, virtualenv et virtualenvwrapper" class="read-more" href="https://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/" aria-label="Plus sur L&#8217;environnement virtuel Python : venv, virtualenv et virtualenvwrapper">Lire plus</a>


feed_id: https://sametmax.com/?p=134
title: Le Pep8 en résumé, c’est quoi ?
uri: Le-Pep8-en-résumé-c-est-quoi
url: https://sametmax.com/le-pep8-en-resume/
content:
PEP8 est un ensemble de conventions et de règles qui définissent un format standard pour le code Python. Ce format est reconnu par les développeurs et les développeuses Python, et permet une meilleure compréhension et une lecture plus fluide du code source. Il existe des outils pour vérifier automatiquement si le code Python que vous ... <a title="Le Pep8 en résumé, c&#8217;est quoi ?" class="read-more" href="https://sametmax.com/le-pep8-en-resume/" aria-label="Plus sur Le Pep8 en résumé, c&#8217;est quoi ?">Lire plus</a>


feed_id: https://sametmax.com/?p=181
title: À quel GAFAM appartient Youtube ?
uri: À-quel-GAFAM-appartient-Youtube
url: https://sametmax.com/a-quel-gafam-appartient-youtube/
content:
Les GAFAM, acronyme pour Google, Apple, Facebook, Amazon et Microsoft, sont des entreprises technologiques qui sont les plus grandes du monde. Les GAFAM sont connues pour occuper le marché des médias numériques et de l&#8217;information, de l&#8217;éducation et de l&#8217;intégration des technologies. Une question que les gens se posent souvent est : à quel GAFAM ... <a title="À quel GAFAM appartient Youtube ?" class="read-more" href="https://sametmax.com/a-quel-gafam-appartient-youtube/" aria-label="Plus sur À quel GAFAM appartient Youtube ?">Lire plus</a>


feed_id: https://sametmax.com/?p=177
title: À quel GAFAM WhatsApp appartient-il ?
uri: À-quel-GAFAM-WhatsApp-appartient-il
url: https://sametmax.com/a-quel-gafam-whatsapp-appartient-il/
content:
Le GAFAM est un acronyme qui regroupe les plus grandes entreprises technologiques du monde : Google, Apple, Facebook, Amazon et Microsoft. Les GAFAM sont les plus grandes entreprises mondiales en termes de capitalisation boursière et de ressources et constituent une force majeure dans l&#8217;industrie technologique. Mais quelle entreprise appartient à quel GAFAM ? Dans cet ... <a title="À quel GAFAM WhatsApp appartient-il ?" class="read-more" href="https://sametmax.com/a-quel-gafam-whatsapp-appartient-il/" aria-label="Plus sur À quel GAFAM WhatsApp appartient-il ?">Lire plus</a>


feed_id: https://sametmax.com/?p=173
title: A quel gafam linkedin appartient-il ?
uri: A-quel-gafam-linkedin-appartient-il
url: https://sametmax.com/a-quel-gafam-linkedin-appartient-il/
content:
Le GAFAM (Google, Apple, Facebook, Amazon et Microsoft) et LinkedIn sont deux marques leader dans leur secteur, qui ont des liens entre eux. Dans cet article, nous examinerons quelle GAFAM est liée à LinkedIn et comment cette relation peut être bénéfique pour les deux entreprises. Quelle GAFAM est liée à LinkedIn ? Microsoft et LinkedIn ... <a title="A quel gafam linkedin appartient-il ?" class="read-more" href="https://sametmax.com/a-quel-gafam-linkedin-appartient-il/" aria-label="Plus sur A quel gafam linkedin appartient-il ?">Lire plus</a>


feed_id: https://sametmax.com/?p=169
title: À quel GAFAM Instagram appartient-il ?
uri: À-quel-GAFAM-Instagram-appartient-il
url: https://sametmax.com/a-quel-gafam-instagram-appartient-il/
content:
Instagram est l&#8217;une des plateformes sociales les plus connues et les plus utilisées de nos jours. Avec plus de 1 milliard d&#8217;utilisateurs actifs mensuels, cette application s&#8217;est rapidement imposée comme étant la préférée des réseaux sociaux. Mais quel est le GAFAM (Google, Apple, Facebook, Amazon et Microsoft) qui est à l&#8217;origine de ce succès ? ... <a title="À quel GAFAM Instagram appartient-il ?" class="read-more" href="https://sametmax.com/a-quel-gafam-instagram-appartient-il/" aria-label="Plus sur À quel GAFAM Instagram appartient-il ?">Lire plus</a>


feed_id: https://sametmax.com/?p=195
title: Comment calculer le prix psychologique d’un produit ?
uri: Comment-calculer-le-prix-psychologique-d-un-produit
url: https://sametmax.com/comment-calculer-le-prix-psychologique-dun-produit/
content:
Le prix psychologique est le prix que les consommateurs sont prêts à payer pour un produit ou un service. Il est basé sur la perception qu&#8217;ils ont des avantages et des inconvénients du produit ou du service et sur leur sentiment général envers lui. La détermination du prix psychologique est un processus complexe qui comprend ... <a title="Comment calculer le prix psychologique d&#8217;un produit ?" class="read-more" href="https://sametmax.com/comment-calculer-le-prix-psychologique-dun-produit/" aria-label="Plus sur Comment calculer le prix psychologique d&#8217;un produit ?">Lire plus</a>


feed_id: https://sametmax.com/?p=191
title: Quelles sont les 4 stratégies de prix ?
uri: Quelles-sont-les-4-stratégies-de-prix
url: https://sametmax.com/quelles-sont-les-3-strategies-de-prix/
content:
Les stratégies de prix sont un outil très puissant destiné à orienter et à influencer les besoins des consommateurs et leur comportement d&#8217;achat. Les entreprises ont souvent recours à ces stratégies afin de répondre aux besoins spécifiques des consommateurs et de maximiser leurs profits. Stratégie Objectif Coût Stratégie de pénétration Pénétrer le marché et s&#8217;imposer ... <a title="Quelles sont les 4 stratégies de prix ?" class="read-more" href="https://sametmax.com/quelles-sont-les-3-strategies-de-prix/" aria-label="Plus sur Quelles sont les 4 stratégies de prix ?">Lire plus</a>


feed_id: https://sametmax.com/?p=187
title: Qu’est-ce qu’une stratégie d’écrémage ?
uri: Qu-est-ce-qu-une-stratégie-d-écrémage
url: https://sametmax.com/quest-ce-quune-strategie-decremage/
content:
La stratégie d&#8217;écrémage est une technique de marketing qui consiste à fixer un prix plus élevé que la moyenne pour un produit ou un service afin de maximiser les profits. En effet, en imposant un prix plus élevé que la moyenne, les consommateurs seront sélectionnés de manière mécanique en fonction de leur valeur et leurs ... <a title="Qu&#8217;est-ce qu&#8217;une stratégie d&#8217;écrémage ?" class="read-more" href="https://sametmax.com/quest-ce-quune-strategie-decremage/" aria-label="Plus sur Qu&#8217;est-ce qu&#8217;une stratégie d&#8217;écrémage ?">Lire plus</a>


feed_id: https://sametmax.com/?p=226
title: Mettre automatiquement DEBUG sur False en production pour Django
uri: Mettre-automatiquement-DEBUG-sur-False-en-production-pour-Django
url: https://sametmax.com/mettre-automatiquement-debug-sur-false-en-production-pour-django/
content:
L’avantage des fichiers de settings en pur Python, c’est qu’on peut faire des trucs mignons comme : import socket &#160; if socket.gethostname() == &#8216;monsupersite.com&#8217;: DEBUG = False else: DEBUG = True


feed_id: https://sametmax.com/?p=217
title: Manipuler les dates et les durées en Python
uri: Manipuler-les-dates-et-les-durées-en-Python
url: https://sametmax.com/manipuler-les-dates-et-les-durees-en-python/
content:
Cet article a été repris par la rédaction pour rendre hommage au site sametmax.com qui a tant apporté a la communauté python Manipuler des dates, c’est chaud. Le calendrier, c’est plein de subtilités comme les années bissextiles, les mois qui ont 4 possibilités de nombre de jours, les semaines qui commencent un dimanche aux US ... <a title="Manipuler les dates et les durées en Python" class="read-more" href="https://sametmax.com/manipuler-les-dates-et-les-durees-en-python/" aria-label="Plus sur Manipuler les dates et les durées en Python">Lire plus</a>


feed_id: https://sametmax.com/?p=218
title: Sérialiser et parser une date en Python: formats de strftime/strptime et timestamps
uri: Sérialiser-et-parser-une-date-en-Python-formats-de-strftime-strptime
url:
https://sametmax.com/serialiser-et-parser-une-date-en-python-formats-de-strftimestrptime-et-timestamps/

content:
Cet article a été repris par notre rédaction en hommage au site sametmax.com et ce qu&#8217;il a apporté à la communauté python Ça fait 10 ans que j’en fais, et je ne me souviens jamais des lettres à utiliser pour les formats. Pourtant j’utilise tout le temps le&#160;même&#160;format: celui de MySQL et JSON par défaut, ... <a title="Sérialiser et parser une date en Python: formats de strftime/strptime et timestamps" class="read-more" href="https://sametmax.com/serialiser-et-parser-une-date-en-python-formats-de-strftimestrptime-et-timestamps/" aria-label="Plus sur Sérialiser et parser une date en Python: formats de strftime/strptime et timestamps">Lire plus</a>


feed_id: https://sametmax.com/?p=212
title: Les 5 forces de porter en marketing, est-ce efficace ?
uri: Les-5-forces-de-porter-en-marketing-est-ce-efficace
url: https://sametmax.com/les-5-forces-de-porter-en-marketing-est-ce-efficace/
content:
La méthode des 5 forces de Porter est un outil d&#8217;analyse stratégique qui permet d&#8217;évaluer la concurrence sur un marché. Elle consiste en une étude de 5 éléments dans le but de définir, avec précision, les opportunités et les menaces qui pèsent sur une entreprise. Qu&#8217;est-ce que la méthode des 5 forces de Porter ? La ... <a title="Les 5 forces de porter en marketing, est-ce efficace ?" class="read-more" href="https://sametmax.com/les-5-forces-de-porter-en-marketing-est-ce-efficace/" aria-label="Plus sur Les 5 forces de porter en marketing, est-ce efficace ?">Lire plus</a>


feed_id: https://sametmax.com/?p=208
title: Quelles sont les caractéristiques d’une personne morale ?
uri: Quelles-sont-les-caractéristiques-d-une-personne-morale
url: https://sametmax.com/quelles-sont-les-caracteristiques-dune-personne-morale/
content:
Une personne morale est une entité juridique reconnue par le droit qui possède des droits et des obligations. Elle peut être une entreprise, une association, une fondation ou une collectivité territoriale. Pour être reconnue comme une personne morale, elle doit remplir certaines caractéristiques. Découvrons ensemble ces caractéristiques. Les personnes morales possèdent une existence juridique Une ... <a title="Quelles sont les caractéristiques d&#8217;une personne morale ?" class="read-more" href="https://sametmax.com/quelles-sont-les-caracteristiques-dune-personne-morale/" aria-label="Plus sur Quelles sont les caractéristiques d&#8217;une personne morale ?">Lire plus</a>


feed_id: https://sametmax.com/?p=204
title: Les objectifs de la production de type kanban
uri: Les-objectifs-de-la-production-de-type-kanban
url: https://sametmax.com/les-objectifs-de-la-production-de-type-kanban/
content:
La production de type Kanban est une méthode de gestion de flux de travail qui a été développée par Toyota. Elle est basée sur le principe de limiter le nombre de tâches en cours et de s&#8217;assurer que chaque tâche est complétée avant de passer à la suivante. Elle est devenue très populaire dans l&#8217;industrie ... <a title="Les objectifs de la production de type kanban" class="read-more" href="https://sametmax.com/les-objectifs-de-la-production-de-type-kanban/" aria-label="Plus sur Les objectifs de la production de type kanban">Lire plus</a>


feed_id: https://sametmax.com/?p=231
title: Comment se connecter à Gmail sur téléphone ?
uri: Comment-se-connecter-à-Gmail-sur-téléphone
url: https://sametmax.com/comment-se-connecter-a-gmail-sur-telephone/
content:
Vous voulez savoir comment se connecter à Gmail sur votre téléphone ? Vous êtes au bon endroit ! Dans cet article, nous allons vous expliquer les étapes à suivre pour pouvoir accéder à votre compte Gmail à partir de votre téléphone. Que ce soit un téléphone Android ou iOS, l&#8217;accès à votre compte Gmail est ... <a title="Comment se connecter à Gmail sur téléphone ?" class="read-more" href="https://sametmax.com/comment-se-connecter-a-gmail-sur-telephone/" aria-label="Plus sur Comment se connecter à Gmail sur téléphone ?">Lire plus</a>


feed_id: https://sametmax.com/?p=235
title: Comment faire un plan de financement ?
uri: Comment-faire-un-plan-de-financement
url: https://sametmax.com/comment-faire-un-plan-de-financement/
content:
Un plan de financement est le tableau qui résume votre stratégie, et qui décrit les étapes nécessaires pour obtenir les ressources dont vous avez besoin pour financer votre projet. Il s&#8217;agit d&#8217;un tableau indispensable à toute entreprise, de grande ou de petite taille. De plus, il est essentiel qu’une entreprise dispose d&#8217;un plan de financement ... <a title="Comment faire un plan de financement ?" class="read-more" href="https://sametmax.com/comment-faire-un-plan-de-financement/" aria-label="Plus sur Comment faire un plan de financement ?">Lire plus</a>


feed_id: https://sametmax.com/?p=238
title: Pourquoi créer un site internet pour votre entreprise ?
uri: Pourquoi-créer-un-site-internet-pour-votre-entreprise
url: https://sametmax.com/pourquoi-creer-un-site-internet-pour-votre-entreprise/
content:
Avoir un site web est essentiel pour inspirer confiance et maîtriser sa communication en ligne. En effet, 56% des internautes n&#8217;accordent pas leur confiance aux entreprises qui n&#8217;en possèdent pas. Un site web permet de se positionner comme un expert dans son secteur et d&#8217;attirer 55% de visiteurs supplémentaires. Comment se comportent les internautes en ... <a title="Pourquoi créer un site internet pour votre entreprise ?" class="read-more" href="https://sametmax.com/pourquoi-creer-un-site-internet-pour-votre-entreprise/" aria-label="Plus sur Pourquoi créer un site internet pour votre entreprise ?">Lire plus</a>


feed_id: https://sametmax.com/?p=241
title: Comment chiffrer le développement d’un site web ?
uri: Comment-chiffrer-le-développement-d-un-site-web
url: https://sametmax.com/comment-chiffrer-le-developpement-dun-site-web/
content:
Le développement d&#8217;un site web est une tâche complexe qui nécessite une bonne planification et des techniques adaptées pour le chiffrer. Vous allez devoir comprendre ... <a title="Comment chiffrer le développement d&#8217;un site web ?" class="read-more" href="https://sametmax.com/comment-chiffrer-le-developpement-dun-site-web/" aria-label="Plus sur Comment chiffrer le développement d&#8217;un site web ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=266
title: Methodologie Smart : Utilité et Objectifs
uri: Methodologie-Smart-Utilité-et-Objectifs
url: https://sametmax.com/methodologie-smart/
content:
La méthodologie Smart est une technique de planification qui consiste à définir des objectifs précis, mesurables, atteignables, réalisables et temporellement limités. Elle peut être utilisée ... <a title="Methodologie Smart : Utilité et Objectifs" class="read-more" href="https://sametmax.com/methodologie-smart/" aria-label="Plus sur Methodologie Smart : Utilité et Objectifs">Lire l'article</a>


feed_id: https://sametmax.com/?p=252
title: Maintien en Condition Opérationnelle informatique : définitions et utilité
uri: Maintien-en-Condition-Opérationnelle-informatique-définitions-et-u
url: https://sametmax.com/mco-definitions-et-utilite/
content:
Le MCO (Maintien en Condition Opérationnelle) est un ensemble de stratégies qui permet de garantir la disponibilité permanente des applications, des infrastructures et des matériels. ... <a title="Maintien en Condition Opérationnelle informatique : définitions et utilité" class="read-more" href="https://sametmax.com/mco-definitions-et-utilite/" aria-label="Plus sur Maintien en Condition Opérationnelle informatique : définitions et utilité">Lire l'article</a>


feed_id: https://sametmax.com/?p=247
title: Qu’est-ce que la GMAO : définitions et utilité
uri: Qu-est-ce-que-la-GMAO-définitions-et-utilité
url: https://sametmax.com/gmao-definitions/
content:
La GMAO est un outil informatique qui offre des avantages considérables aux services de maintenance. Il permet d&#8217;accroître l&#8217;efficacité des interventions, d&#8217;améliorer la qualité des ... <a title="Qu&#8217;est-ce que la GMAO : définitions et utilité" class="read-more" href="https://sametmax.com/gmao-definitions/" aria-label="Plus sur Qu&#8217;est-ce que la GMAO : définitions et utilité">Lire l'article</a>


feed_id: https://sametmax.com/?p=258
title: Pourquoi choisir un lettrage 3D pour sa communication ?
uri: Pourquoi-choisir-un-lettrage-3D-pour-sa-communication
url: https://sametmax.com/pourquoi-choisir-un-lettrage-3d-pour-sa-communication/
content:
Le lettrage 3D est une solution moderne et contemporaine pour améliorer la visibilité de votre marque et lui donner une touche d&#8217;originalité. Les lettres 3D ... <a title="Pourquoi choisir un lettrage 3D pour sa communication ?" class="read-more" href="https://sametmax.com/pourquoi-choisir-un-lettrage-3d-pour-sa-communication/" aria-label="Plus sur Pourquoi choisir un lettrage 3D pour sa communication ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=263
title: La différence entre Kanban et Scrum
uri: La-différence-entre-Kanban-et-Scrum
url: https://sametmax.com/la-difference-entre-kanban-et-scrum/
content:
Dans une entreprise, pour ce qui est de la gestion de projet, la méthodologie agile reste la plus utilisée en toute circonstance. Comme preuve, dans ... <a title="La différence entre Kanban et Scrum" class="read-more" href="https://sametmax.com/la-difference-entre-kanban-et-scrum/" aria-label="Plus sur La différence entre Kanban et Scrum">Lire l'article</a>


feed_id: https://sametmax.com/?p=269
title: Chemin critique d’un projet : définitions
uri: Chemin-critique-d-un-projet-définitions
url: https://sametmax.com/chemin-critique/
content:
Le chemin critique est un outil qui permet de déterminer la durée totale d&#8217;un projet. Il s&#8217;agit de la plus longue séquence de tâches qui ... <a title="Chemin critique d&#8217;un projet : définitions" class="read-more" href="https://sametmax.com/chemin-critique/" aria-label="Plus sur Chemin critique d&#8217;un projet : définitions">Lire l'article</a>


feed_id: https://sametmax.com/?p=274
title: Étude d’Opportunité : Définition et Utilités
uri: Étude-d-Opportunité-Définition-et-Utilités
url: https://sametmax.com/etude-dopportunite/
content:
L&#8217;étude d&#8217;opportunité est un outil essentiel pour les entrepreneurs qui souhaitent démarrer leur projet. Elle est une pré-étude qui détaille le potentiel d&#8217;un projet afin ... <a title="Étude d&#8217;Opportunité : Définition et Utilités" class="read-more" href="https://sametmax.com/etude-dopportunite/" aria-label="Plus sur Étude d&#8217;Opportunité : Définition et Utilités">Lire l'article</a>


feed_id: https://sametmax.com/?p=279
title: Pureplayer : quelles sont ces entreprises ?
uri: Pureplayer-quelles-sont-ces-entreprises
url: https://sametmax.com/pureplayer-quelles-sont-ces-entreprises/
content:
Dans un contexte digital qui évolue à une vitesse fulgurante, le terme pureplayer est souvent employé. Mais qu&#8217;est-ce qu&#8217;un pureplayer ? D&#8217;où vient ce terme ... <a title="Pureplayer : quelles sont ces entreprises ?" class="read-more" href="https://sametmax.com/pureplayer-quelles-sont-ces-entreprises/" aria-label="Plus sur Pureplayer : quelles sont ces entreprises ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=282
title: Comment créer un sondage sur Messenger ?
uri: Comment-créer-un-sondage-sur-Messenger
url: https://sametmax.com/sondage-messenger/
content:
Messenger est un outil très pratique pour communiquer avec vos amis, votre famille ou vos collègues. Il est aujourd’hui possible de créer un sondage et ... <a title="Comment créer un sondage sur Messenger ?" class="read-more" href="https://sametmax.com/sondage-messenger/" aria-label="Plus sur Comment créer un sondage sur Messenger ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=286
title: Qu’est-ce que la valeur nette comptable ?
uri: Qu-est-ce-que-la-valeur-nette-comptable
url: https://sametmax.com/valeur-nette-comptable/
content:
La valeur nette comptable est un terme financier qui désigne le montant total des actifs d&#8217;une entreprise, moins ses dettes et ses autres passifs. Ce ... <a title="Qu&#8217;est-ce que la valeur nette comptable ?" class="read-more" href="https://sametmax.com/valeur-nette-comptable/" aria-label="Plus sur Qu&#8217;est-ce que la valeur nette comptable ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=289
title: Comment savoir si une image est libre de droit ?
uri: Comment-savoir-si-une-image-est-libre-de-droit
url: https://sametmax.com/comment-savoir-si-une-image-est-libre-de-droit/
content:
Chaque année, des milliers de personnes se retrouvent confrontées au problème de savoir si une image est libre de droit. Souvent, la personne ne possède ... <a title="Comment savoir si une image est libre de droit ?" class="read-more" href="https://sametmax.com/comment-savoir-si-une-image-est-libre-de-droit/" aria-label="Plus sur Comment savoir si une image est libre de droit ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2366
title: Comment devenir un créateur de site web ?
uri: Comment-devenir-un-créateur-de-site-web
url: https://sametmax.com/comment-devenir-un-createur-de-site-web/
content:
Le web est un domaine en pleine croissance depuis des années. De nombreuses personnes souhaitent être à l&#8217;avant-garde des technologies en devenant créateur de site ... <a title="Comment devenir un créateur de site web ?" class="read-more" href="https://sametmax.com/comment-devenir-un-createur-de-site-web/" aria-label="Plus sur Comment devenir un créateur de site web ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2387
title: Comment contourner une clause de non concurrence ?
uri: Comment-contourner-une-clause-de-non-concurrence
url: https://sametmax.com/comment-contourner-une-clause-de-non-concurrence/
content:
Une clause de non-concurrence est un contrat à durée limitée qui stipule qu&#8217;une personne ne peut pas travailler pour une autre entreprise concurrente, dans un ... <a title="Comment contourner une clause de non concurrence ?" class="read-more" href="https://sametmax.com/comment-contourner-une-clause-de-non-concurrence/" aria-label="Plus sur Comment contourner une clause de non concurrence ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2381
title: Formation intra entreprise : définition et avantages
uri: Formation-intra-entreprise-définition-et-avantages
url: https://sametmax.com/formation-intra-entreprise-definition-et-avantages/
content:
Une formation intra entreprise, ou formation en interne, est une formation spécifique destinée à un groupe d&#8217;employés d&#8217;une même entreprise ou institution, contrairement aux formations ... <a title="Formation intra entreprise : définition et avantages" class="read-more" href="https://sametmax.com/formation-intra-entreprise-definition-et-avantages/" aria-label="Plus sur Formation intra entreprise : définition et avantages">Lire l'article</a>


feed_id: https://sametmax.com/?p=2377
title: Qu’est ce qu’une formation inter entreprise ?
uri: Qu-est-ce-qu-une-formation-inter-entreprise
url: https://sametmax.com/formation-inter-entreprise/
content:
Tout le monde connaît les formations disponibles pour les professionnels en entreprise, mais connaissez-vous la formation inter-entreprise ? Il s&#8217;agit d&#8217;une formation spécifique qui s&#8217;adresse ... <a title="Qu&#8217;est ce qu&#8217;une formation inter entreprise ?" class="read-more" href="https://sametmax.com/formation-inter-entreprise/" aria-label="Plus sur Qu&#8217;est ce qu&#8217;une formation inter entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=297
title: Modele ADKAR : définition de la méthode de gestion
uri: Modele-ADKAR-définition-de-la-méthode-de-gestion
url: https://sametmax.com/modele-adkar-definition/
content:
Le modèle ADKAR est une méthode utile pour le développement d&#8217;un plan de conduite du changement et le management de projet. ADKAR est un acronyme ... <a title="Modele ADKAR : définition de la méthode de gestion" class="read-more" href="https://sametmax.com/modele-adkar-definition/" aria-label="Plus sur Modele ADKAR : définition de la méthode de gestion">Lire l'article</a>


feed_id: https://sametmax.com/?p=2393
title: Qu’elle phrase d’accroche pour attirer le client dans un mail ?
uri: Qu-elle-phrase-d-accroche-pour-attirer-le-client-dans-un-mail
url: https://sametmax.com/phrase-daccroche-pour-attirer-le-client-dans-un-mail/
content:
Une phrase d&#8217;accroche est une pratique essentielle pour réussir à capter l&#8217;attention de votre clientèle lors d&#8217;une communication par mail. En effet, elle doit être ... <a title="Qu&#8217;elle phrase d&#8217;accroche pour attirer le client dans un mail ?" class="read-more" href="https://sametmax.com/phrase-daccroche-pour-attirer-le-client-dans-un-mail/" aria-label="Plus sur Qu&#8217;elle phrase d&#8217;accroche pour attirer le client dans un mail ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=300
title: Quels sites web utilisent des algorithmes de recommandation ?
uri: Quels-sites-web-utilisent-des-algorithmes-de-recommandation
url: https://sametmax.com/quels-sites-web-utilisent-des-algorithmes-de-recommandation/
content:
Les algorithmes de recommandation sont de plus en plus utilisés aujourd’hui pour améliorer les expériences utilisateur. Ces algorithmes sont conçus pour recueillir des informations spécifiques ... <a title="Quels sites web utilisent des algorithmes de recommandation ?" class="read-more" href="https://sametmax.com/quels-sites-web-utilisent-des-algorithmes-de-recommandation/" aria-label="Plus sur Quels sites web utilisent des algorithmes de recommandation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2353
title: Veille informationnelle : définition
uri: Veille-informationnelle-définition
url: https://sametmax.com/veille-informationnelle-definition/
content:
La veille informationnelle est une pratique qui s&#8217;est développée ces dernières années et qui vise à recueillir et à analyser des sources d&#8217;informations afin d&#8217;être ... <a title="Veille informationnelle : définition" class="read-more" href="https://sametmax.com/veille-informationnelle-definition/" aria-label="Plus sur Veille informationnelle : définition">Lire l'article</a>


feed_id: https://sametmax.com/?p=2445
title: Combien coute la création d’un site e-commerce ?
uri: Combien-coute-la-création-d-un-site-e-commerce
url: https://sametmax.com/combien-coute-la-creation-dun-site-e-commerce/
content:
Quand on lance un projet de commerce en ligne, il faut connaître le budget nécessaire pour la création du site web. Cet article se concentrera ... <a title="Combien coute la création d’un site e-commerce ?" class="read-more" href="https://sametmax.com/combien-coute-la-creation-dun-site-e-commerce/" aria-label="Plus sur Combien coute la création d’un site e-commerce ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2448
title: Pourquoi créer un site e-commerce ?
uri: Pourquoi-créer-un-site-e-commerce
url: https://sametmax.com/pourquoi-creer-un-site-e-commerce/
content:
Le commerce en ligne a considérablement augmenté ces dernières années. La vente sur internet est devenue plus facile que jamais et beaucoup de commerçants s&#8217;inscrivent ... <a title="Pourquoi créer un site e-commerce ?" class="read-more" href="https://sametmax.com/pourquoi-creer-un-site-e-commerce/" aria-label="Plus sur Pourquoi créer un site e-commerce ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2468
title: Formez-vous et devenez un éducateur Montessori qualifié en France !
uri: Formez-vous-et-devenez-un-éducateur-Montessori-qualifié-en-France
url: https://sametmax.com/formez-vous-et-devenez-un-educateur-montessori-qualifie-en-france/
content:
Avec le succès de l’éducation Montessori croissant en France ces dernières années, de plus en plus de personnes cherchent à se former et à obtenir ... <a title="Formez-vous et devenez un éducateur Montessori qualifié en France !" class="read-more" href="https://sametmax.com/formez-vous-et-devenez-un-educateur-montessori-qualifie-en-france/" aria-label="Plus sur Formez-vous et devenez un éducateur Montessori qualifié en France !">Lire l'article</a>


feed_id: https://sametmax.com/?p=2359
title: Comment calculer le taux d’engagement d’Instagram ?
uri: Comment-calculer-le-taux-d-engagement-d-Instagram
url: https://sametmax.com/comment-calculer-le-taux-dengagement-dinstagram/
content:
Le taux d&#8217;engagement sur un compte de réseau social est un indicateur essentiel pour évaluer la pertinence d&#8217;une stratégie de communication et de marketing. Il ... <a title="Comment calculer le taux d&#8217;engagement d&#8217;Instagram ?" class="read-more" href="https://sametmax.com/comment-calculer-le-taux-dengagement-dinstagram/" aria-label="Plus sur Comment calculer le taux d&#8217;engagement d&#8217;Instagram ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2451
title: Quels sont les risques du portage salarial ?
uri: Quels-sont-les-risques-du-portage-salarial
url: https://sametmax.com/quels-sont-les-risques-du-portage-salarial/
content:
Le portage salarial est un contrat de travail atypique qui offre des avantages aux entrepreneurs et indépendants. Mais le portage salarial n&#8217;est pas sans risques&#160;; ... <a title="Quels sont les risques du portage salarial&#160;?" class="read-more" href="https://sametmax.com/quels-sont-les-risques-du-portage-salarial/" aria-label="Plus sur Quels sont les risques du portage salarial&#160;?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2362
title: Comment savoir si une entreprise a une assurance décennale ?
uri: Comment-savoir-si-une-entreprise-a-une-assurance-décennale
url: https://sametmax.com/comment-savoir-si-une-entreprise-a-une-assurance-decennale/
content:
Une assurance décennale est une assurance qui protège l’entrepreneur contre les erreurs ou omissions dans la réalisation de son oeuvre. Elle est très importante pour ... <a title="Comment savoir si une entreprise a une assurance décennale ?" class="read-more" href="https://sametmax.com/comment-savoir-si-une-entreprise-a-une-assurance-decennale/" aria-label="Plus sur Comment savoir si une entreprise a une assurance décennale ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2474
title: Quel est le protocole pour la réception des courriers ?
uri: Quel-est-le-protocole-pour-la-réception-des-courriers
url: https://sametmax.com/quel-est-le-protocole-pour-la-reception-des-courriers/
content:
La question de savoir quel est le protocole pour la réception des courriers est l&#8217;une des plus importantes que les utilisateurs doivent se poser, en ... <a title="Quel est le protocole pour la réception des courriers ?" class="read-more" href="https://sametmax.com/quel-est-le-protocole-pour-la-reception-des-courriers/" aria-label="Plus sur Quel est le protocole pour la réception des courriers ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2402
title: Comment mettre en place une stratégie d’internationalisation au sein de votre entreprise ?
uri: Comment-mettre-en-place-une-stratégie-d-internationalisation-au-sei
url:
https://sametmax.com/comment-mettre-en-place-une-strategie-dinternationalisation-au-sein-de-votre-entreprise/

content:
L&#8217;internalisation est un concept très important utilisé par les entreprises pour se développer à l&#8217;échelle internationale. Elle implique le déplacement et la distribution des produits, ... <a title="Comment mettre en place une stratégie d’internationalisation au sein de votre entreprise ?" class="read-more" href="https://sametmax.com/comment-mettre-en-place-une-strategie-dinternationalisation-au-sein-de-votre-entreprise/" aria-label="Plus sur Comment mettre en place une stratégie d’internationalisation au sein de votre entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2464
title: Comment comptabiliser le portage salarial ?
uri: Comment-comptabiliser-le-portage-salarial
url: https://sametmax.com/comment-comptabiliser-le-portage-salarial/
content:
Le portage salarial permet à un professionnel d&#8217;exercer en tant qu&#8217;indépendant tout en bénéficiant de l&#8217;accompagnement et des protections sociales d&#8217;une entreprise. Il s&#8217;agit donc ... <a title="Comment comptabiliser le portage salarial ?" class="read-more" href="https://sametmax.com/comment-comptabiliser-le-portage-salarial/" aria-label="Plus sur Comment comptabiliser le portage salarial ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2459
title: Combien coute le portage salarial ?
uri: Combien-coute-le-portage-salarial
url: https://sametmax.com/combien-coute-le-portage-salarial/
content:
Le portage salarial est un dispositif qui permet à des personnes désirant travailler de manière indépendante de bénéficier de tous les avantages inhérents à un ... <a title="Combien coute le portage salarial ?" class="read-more" href="https://sametmax.com/combien-coute-le-portage-salarial/" aria-label="Plus sur Combien coute le portage salarial ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2454
title: Comment comptabiliser du mobilier de bureau ?
uri: Comment-comptabiliser-du-mobilier-de-bureau
url: https://sametmax.com/comment-comptabiliser-du-mobilier-de-bureau/
content:
Le mobilier de bureau est essentiel pour les entreprises et autres organismes qui travaillent avec des documents papiers ou numériques. Afin d&#8217;avoir une comptabilité correcte, ... <a title="Comment comptabiliser du mobilier de bureau ?" class="read-more" href="https://sametmax.com/comment-comptabiliser-du-mobilier-de-bureau/" aria-label="Plus sur Comment comptabiliser du mobilier de bureau ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2369
title: Comment faire l’arborescence d’un site web ?
uri: Comment-faire-l-arborescence-d-un-site-web
url: https://sametmax.com/comment-faire-larborescence-dun-site-web/
content:
L&#8217;arborescence d&#8217;un site web est un aspect important et souvent sous-estimé du web design. Une arborescence bien organisée est essentielle pour assurer que les visiteurs ... <a title="Comment faire l&#8217;arborescence d&#8217;un site web ?" class="read-more" href="https://sametmax.com/comment-faire-larborescence-dun-site-web/" aria-label="Plus sur Comment faire l&#8217;arborescence d&#8217;un site web ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=293
title: Gestion de projet : Kanban vs Agile
uri: Gestion-de-projet-Kanban-vs-Agile
url: https://sametmax.com/gestion-de-projet-kanban-vs-agile/
content:
Que ce soit les méthodes Kanban ou Scrum, elles proviennent toutes de la méthodologie de gestion de projet Agile, la première méthode à être utilisée ... <a title="Gestion de projet : Kanban vs Agile" class="read-more" href="https://sametmax.com/gestion-de-projet-kanban-vs-agile/" aria-label="Plus sur Gestion de projet : Kanban vs Agile">Lire l'article</a>


feed_id: https://sametmax.com/?p=2372
title: Comment faire un compte rendu de réunion ?
uri: Comment-faire-un-compte-rendu-de-réunion
url: https://sametmax.com/comment-faire-un-compte-rendu-de-reunion/
content:
Les comptes-rendus de réunions sont un moyen essentiel de documenter les décisions qui ont été prises et les sujets qui ont été discutés. Une bonne ... <a title="Comment faire un compte rendu de réunion ?" class="read-more" href="https://sametmax.com/comment-faire-un-compte-rendu-de-reunion/" aria-label="Plus sur Comment faire un compte rendu de réunion ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2406
title: Coeur de cible : comment le définir ?
uri: Coeur-de-cible-comment-le-définir
url: https://sametmax.com/coeur-de-cible-comment-le-definir/
content:
Le cœur de cible est un concept marketing qui sert à identifier le public principal visé par une campagne ou un produit. Il est nécéssaire ... <a title="Coeur de cible : comment le définir ?" class="read-more" href="https://sametmax.com/coeur-de-cible-comment-le-definir/" aria-label="Plus sur Coeur de cible : comment le définir ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2411
title: Programmer ses publications sur Instagram pour une meilleure visibilité
uri: Programmer-ses-publications-sur-Instagram-pour-une-meilleure-visibilit
url: https://sametmax.com/programmer-ses-publications-sur-instagram-pour-une-meilleure-visibilite/
content:
Les réseaux sociaux sont devenus incontournables aujourd’hui. Ils permettent d’atteindre des milliers, voire des millions d&#8217;utilisateurs à travers le monde. Instagram est l’un des plus ... <a title="Programmer ses publications sur Instagram pour une meilleure visibilité" class="read-more" href="https://sametmax.com/programmer-ses-publications-sur-instagram-pour-une-meilleure-visibilite/" aria-label="Plus sur Programmer ses publications sur Instagram pour une meilleure visibilité">Lire l'article</a>


feed_id: https://sametmax.com/?p=2509
title: La méthode DESC : une technique très efficace pour exprimer un désaccord
uri: La-méthode-DESC-une-technique-très-efficace-pour-exprimer-un-désa
url: https://sametmax.com/la-methode-desc-une-technique-tres-efficace-pour-exprimer-un-desaccord/
content:
Si vous vous trouvez un jour en désaccord avec quelqu&#8217;un au travail ou si vous devez confronter un employé à propos de son erreur, la ... <a title="La méthode DESC : une technique très efficace pour exprimer un désaccord" class="read-more" href="https://sametmax.com/la-methode-desc-une-technique-tres-efficace-pour-exprimer-un-desaccord/" aria-label="Plus sur La méthode DESC : une technique très efficace pour exprimer un désaccord">Lire l'article</a>


feed_id: https://sametmax.com/?p=2516
title: Devenir développeur python : Fiche métier, formation et salaire
uri: Devenir-développeur-python-Fiche-métier-formation-et-salaire
url: https://sametmax.com/devenir-developpeur-python-fiche-metier-formation-et-salaire/
content:
Vous êtes-vous déjà demandé ce qu&#8217;il fallait faire pour devenir un développeur Python ? Il s&#8217;agit d&#8217;une spécialisation très recherchée, et avec les bonnes compétences ... <a title="Devenir développeur python : Fiche métier, formation et salaire" class="read-more" href="https://sametmax.com/devenir-developpeur-python-fiche-metier-formation-et-salaire/" aria-label="Plus sur Devenir développeur python : Fiche métier, formation et salaire">Lire l'article</a>


feed_id: https://sametmax.com/?p=2503
title: Formulaire S3201 : Téléchargement et guide pour le remplir
uri: Formulaire-S3201-Téléchargement-et-guide-pour-le-remplir
url: https://sametmax.com/formulaire-s3201/
content:
En tant qu&#8217;employeur, vous êtes tenu de remettre une attestation de salaire &#8211; souvent appelée Cerfa 11135*4 ou formulaire S3201 &#8211; à la caisse d&#8217;assurance ... <a title="Formulaire S3201 : Téléchargement et guide pour le remplir" class="read-more" href="https://sametmax.com/formulaire-s3201/" aria-label="Plus sur Formulaire S3201 : Téléchargement et guide pour le remplir">Lire l'article</a>


feed_id: https://sametmax.com/?p=2415
title: Qu’est-ce que c’est que la stratégie omnicanal ?
uri: Qu-est-ce-que-c-est-que-la-stratégie-omnicanal
url: https://sametmax.com/quest-ce-que-cest-que-la-strategie-omnicanal/
content:
La Stratégie omnicanal est une nouvelle méthode de marketing qui se focalise sur le client, et permet aux marques d’offrir des expériences plus personnalisées. Elle ... <a title="Qu&#8217;est-ce que c&#8217;est que la stratégie omnicanal ?" class="read-more" href="https://sametmax.com/quest-ce-que-cest-que-la-strategie-omnicanal/" aria-label="Plus sur Qu&#8217;est-ce que c&#8217;est que la stratégie omnicanal ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2422
title: Comment la méthode Soncas peut améliorer votre vie ?
uri: Comment-la-méthode-Soncas-peut-améliorer-votre-vie
url: https://sametmax.com/comment-la-methode-soncas-peut-ameliorer-votre-vie/
content:
Savoir identifier ses envies et ses besoins est une étape essentielle pour atteindre le confort et le bien-être. La bonne nouvelle est que c&#8217;est précisément ... <a title="Comment la méthode Soncas peut améliorer votre vie ?" class="read-more" href="https://sametmax.com/comment-la-methode-soncas-peut-ameliorer-votre-vie/" aria-label="Plus sur Comment la méthode Soncas peut améliorer votre vie ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2500
title: Travail en 3×8 : Fonctionnement et avantages
uri: Travail-en-3-8-Fonctionnement-et-avantages
url: https://sametmax.com/travail-en-3x8-fonctionnement-et-avantages/
content:
Pour les entreprises ayant une charge de travail importante, le travail en 3&#215;8 est une solution fortement recommandée qui offre de nombreux avantages. Ce type ... <a title="Travail en 3&#215;8 : Fonctionnement et avantages" class="read-more" href="https://sametmax.com/travail-en-3x8-fonctionnement-et-avantages/" aria-label="Plus sur Travail en 3&#215;8 : Fonctionnement et avantages">Lire l'article</a>


feed_id: https://sametmax.com/?p=2428
title: Comment changer le nom d’une page Facebook ?
uri: Comment-changer-le-nom-d-une-page-Facebook
url: https://sametmax.com/comment-changer-le-nom-dune-page-facebook/
content:
Changer le nom d’une page Facebook peut être utile et nécessaire pour plusieurs raisons. Peut-être que vous avez récemment créé une page et que vous ... <a title="Comment changer le nom d&#8217;une page Facebook ?" class="read-more" href="https://sametmax.com/comment-changer-le-nom-dune-page-facebook/" aria-label="Plus sur Comment changer le nom d&#8217;une page Facebook ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2608
title: Comment faire une Analyse SWOT d’un projet ?
uri: Comment-faire-une-Analyse-SWOT-d-un-projet
url: https://sametmax.com/comment-faire-une-analyse-swot-dun-projet/
content:
L’analyse SWOT est une méthode de stratégie et de planification marketing utilisée pour évaluer l’état actuel et l’orientation future d’une entreprise. Elle permet d’évaluer la ... <a title="Comment faire une Analyse SWOT d&#8217;un projet ?" class="read-more" href="https://sametmax.com/comment-faire-une-analyse-swot-dun-projet/" aria-label="Plus sur Comment faire une Analyse SWOT d&#8217;un projet ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2432
title: Peut-on fermer une entreprise du jour au lendemain ?
uri: Peut-on-fermer-une-entreprise-du-jour-au-lendemain
url: https://sametmax.com/peut-on-fermer-une-entreprise-du-jour-au-lendemain/
content:
Lorsqu’un chef d’entreprise envisage de fermer sa société, cela nécessite de prendre un certain nombre de décisions et d’accomplir certaines formalités. Mais est-il possible de ... <a title="Peut-on fermer une entreprise du jour au lendemain ?" class="read-more" href="https://sametmax.com/peut-on-fermer-une-entreprise-du-jour-au-lendemain/" aria-label="Plus sur Peut-on fermer une entreprise du jour au lendemain ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2616
title: 1300 brut en net : calculateur salaire brut en net
uri: 1300-brut-en-net-calculateur-salaire-brut-en-net
url: https://sametmax.com/1300-brut-en-net-calculateur-salaire-brut-en-net/
content:
Vous avez un salaire mensuel de 1300 brut et vous cherchez à savoir comment le transformer en net ? Vous souhaitez comprendre quelles sont les ... <a title="1300 brut en net : calculateur salaire brut en net" class="read-more" href="https://sametmax.com/1300-brut-en-net-calculateur-salaire-brut-en-net/" aria-label="Plus sur 1300 brut en net : calculateur salaire brut en net">Lire l'article</a>


feed_id: https://sametmax.com/?p=2613
title: 3000 brut en net : Comment calculer son salaire ?
uri: 3000-brut-en-net-Comment-calculer-son-salaire
url: https://sametmax.com/3000-brut-en-net/
content:
Savoir quelle est la somme effectivement perçue par un salarié lorsqu&#8217;il est rémunéré à raison de 3000 euros bruts par mois, peut s&#8217;avérer complexe. Le ... <a title="3000 brut en net : Comment calculer son salaire ?" class="read-more" href="https://sametmax.com/3000-brut-en-net/" aria-label="Plus sur 3000 brut en net : Comment calculer son salaire ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2644
title: Comment verrouiller un téléphone égaré ?
uri: Comment-verrouiller-un-téléphone-égaré
url: https://sametmax.com/comment-verrouiller-un-telephone-egare/
content:
Perdre son téléphone est sans doute l&#8217;une des choses les plus frustrantes qui puissent arriver. Néanmoins, il existe des moyens très efficaces pour verrouiller à ... <a title="Comment verrouiller un téléphone égaré ?" class="read-more" href="https://sametmax.com/comment-verrouiller-un-telephone-egare/" aria-label="Plus sur Comment verrouiller un téléphone égaré ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2641
title: Comment surveiller sa e-réputation ?
uri: Comment-surveiller-sa-e-réputation
url: https://sametmax.com/comment-surveiller-sa-e-reputation/
content:
La surveillance de l&#8217;e-réputation est un élément essentiel pour les entreprises et les marques, car elle a une influence directe sur leur image en ligne. ... <a title="Comment surveiller sa e-réputation ?" class="read-more" href="https://sametmax.com/comment-surveiller-sa-e-reputation/" aria-label="Plus sur Comment surveiller sa e-réputation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2478
title: Comment localiser un numéro de téléphone avec Google Maps ?
uri: Comment-localiser-un-numéro-de-téléphone-avec-Google-Maps
url: https://sametmax.com/comment-localiser-un-numero-de-telephone-avec-google-maps/
content:
Google Maps est l’un des services les plus connus et les plus populaires offerts par le géant américain. À part la possibilité de planifier une ... <a title="Comment localiser un numéro de téléphone avec Google Maps ?" class="read-more" href="https://sametmax.com/comment-localiser-un-numero-de-telephone-avec-google-maps/" aria-label="Plus sur Comment localiser un numéro de téléphone avec Google Maps ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2621
title: 1000 brut en net : Calculer votre salaire
uri: 1000-brut-en-net-Calculer-votre-salaire
url: https://sametmax.com/1000-brut-en-net/
content:
Vous êtes à la recherche d&#8217;un nouvel emploi et vous souhaitez savoir ce que vous rapportera votre salaire annuel brut estimé à 1000€. En effet, ... <a title="1000 brut en net : Calculer votre salaire" class="read-more" href="https://sametmax.com/1000-brut-en-net/" aria-label="Plus sur 1000 brut en net : Calculer votre salaire">Lire l'article</a>


feed_id: https://sametmax.com/?p=2628
title: 1800 brut en net : calcul du salaire brut en net
uri: 1800-brut-en-net-calcul-du-salaire-brut-en-net
url: https://sametmax.com/1800-brut-en-net-calcul-du-salaire-brut-en-net/
content:
Entendre le mot “salaire” est toujours un sentiment gratifiant. Toutefois, il y a beaucoup plus à savoir qu&#8217;un simple montant brut. Dans cet article, nous ... <a title="1800 brut en net : calcul du salaire brut en net" class="read-more" href="https://sametmax.com/1800-brut-en-net-calcul-du-salaire-brut-en-net/" aria-label="Plus sur 1800 brut en net : calcul du salaire brut en net">Lire l'article</a>


feed_id: https://sametmax.com/?p=2631
title: 1900 brut en net : calculer le salaire
uri: 1900-brut-en-net-calculer-le-salaire
url: https://sametmax.com/1900-brut-en-net-calculer-le-salaire/
content:
Le salaire net désigne le montant que vous recevez sur votre compte à la banque. Après avoir soustrait le précompte professionnel et les cotisations de ... <a title="1900 brut en net : calculer le salaire" class="read-more" href="https://sametmax.com/1900-brut-en-net-calculer-le-salaire/" aria-label="Plus sur 1900 brut en net : calculer le salaire">Lire l'article</a>


feed_id: https://sametmax.com/?p=2436
title: Freelance informatique : Quel statut juridique choisir ?
uri: Freelance-informatique-Quel-statut-juridique-choisir
url: https://sametmax.com/freelance-informatique-quel-statut-juridique-choisir/
content:
Avoir une activité freelance est devenu de plus en plus tendance en ce moment. Pour de nombreux salariés, cette conversion professionnelle est motivée par le ... <a title="Freelance informatique : Quel statut juridique choisir ?" class="read-more" href="https://sametmax.com/freelance-informatique-quel-statut-juridique-choisir/" aria-label="Plus sur Freelance informatique : Quel statut juridique choisir ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2678
title: Scolinfo: comment se connecter
uri: Scolinfo-comment-se-connecter
url: https://sametmax.com/scolinfo/
content:
Il est essentiel de développer une relation de cohésion entre tous les membres d&#8217;un système éducatif, notamment entre les élèves, les parents, les enseignants et ... <a title="Scolinfo: comment se connecter" class="read-more" href="https://sametmax.com/scolinfo/" aria-label="Plus sur Scolinfo: comment se connecter">Lire l'article</a>


feed_id: https://sametmax.com/?p=2496
title: Comment choisir sa formation pour devenir développeur web ?
uri: Comment-choisir-sa-formation-pour-devenir-développeur-web
url: https://sametmax.com/comment-choisir-sa-formation-pour-devenir-developpeur-web/
content:
Le monde digital est en pleine croissance surtout avec le grand nombre d&#8217;entreprises qui migrent leur activité commerciale sur le web. Ainsi, devenir un développeur ... <a title="Comment choisir sa formation pour devenir développeur web ?" class="read-more" href="https://sametmax.com/comment-choisir-sa-formation-pour-devenir-developpeur-web/" aria-label="Plus sur Comment choisir sa formation pour devenir développeur web ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2521
title: Combien gagne un détective privé ?
uri: Combien-gagne-un-détective-privé
url: https://sametmax.com/combien-gagne-un-detective-prive/
content:
Souvent relatée dans les romans policiers, la carrière professionnelle d’un détective privé figure comme un métier passionnant et plein de surprise. Dans le monde du ... <a title="Combien gagne un détective privé ?" class="read-more" href="https://sametmax.com/combien-gagne-un-detective-prive/" aria-label="Plus sur Combien gagne un détective privé ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2525
title: Herpétologiste : focus sur ce métier
uri: Herpétologiste-focus-sur-ce-métier
url: https://sametmax.com/herpetologiste-focus-sur-ce-metier/
content:
Il existe de nombreux métiers scientifiques qui traitent de la biodiversité, l’herpétologie en fait partie. Cette science qui étudie les animaux qui rampent dont les ... <a title="Herpétologiste : focus sur ce métier" class="read-more" href="https://sametmax.com/herpetologiste-focus-sur-ce-metier/" aria-label="Plus sur Herpétologiste : focus sur ce métier">Lire l'article</a>


feed_id: https://sametmax.com/?p=2724
title: Quelles sont les meilleures pratiques pour la segmentation du marché ?
uri: Quelles-sont-les-meilleures-pratiques-pour-la-segmentation-du-marché
url: https://sametmax.com/segmentation-du-marche/
content:
La segmentation du marché est une stratégie marketing importante pour aider les entreprises à mieux connaître leurs clients et à développer des produits ou services ... <a title="Quelles sont les meilleures pratiques pour la segmentation du marché ?" class="read-more" href="https://sametmax.com/segmentation-du-marche/" aria-label="Plus sur Quelles sont les meilleures pratiques pour la segmentation du marché ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2585
title: Comment écrire un mail de relance ?
uri: Comment-écrire-un-mail-de-relance
url: https://sametmax.com/comment-ecrire-un-mail-de-relance/
content:
Avoir une adresse électronique est presque une obligation, que vous soyez un entrepreneur, un chercheur d’emploi, un fournisseur ou un particulier. En effet, à l’heure ... <a title="Comment écrire un mail de relance ?" class="read-more" href="https://sametmax.com/comment-ecrire-un-mail-de-relance/" aria-label="Plus sur Comment écrire un mail de relance ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2697
title: Bourses emploi notaire : un allié pour votre carrière ?
uri: Bourses-emploi-notaire-un-allié-pour-votre-carrière
url: https://sametmax.com/bourses-emploi-notaire/
content:
Les bourses d&#8217;emploi sont des occasions précieuses de développer une carrière en tant que notaire. Les bourses offrent aux candidats la possibilité de gagner une ... <a title="Bourses emploi notaire : un allié pour votre carrière ?" class="read-more" href="https://sametmax.com/bourses-emploi-notaire/" aria-label="Plus sur Bourses emploi notaire : un allié pour votre carrière ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2602
title: Comment élaborer un diagnostic stratégique externe ?
uri: Comment-élaborer-un-diagnostic-stratégique-externe
url: https://sametmax.com/diagnostic-strategique-externe/
content:
Toute entreprise est façonnée par l&#8217;environnement externe, qui se compose de multiples acteurs et parties qui l&#8217;influencent. Cet environnement en constante évolution affecte considérablement le ... <a title="Comment élaborer un diagnostic stratégique externe ?" class="read-more" href="https://sametmax.com/diagnostic-strategique-externe/" aria-label="Plus sur Comment élaborer un diagnostic stratégique externe ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2596
title: Comment mettre en place un team building ?
uri: Comment-mettre-en-place-un-team-building
url: https://sametmax.com/comment-mettre-en-place-un-team-building/
content:
Dans une entreprise, il n&#8217;est pas rare de réaliser des sessions de team building. C&#8217;est quelque chose qui se déroule surtout dans les grandes et ... <a title="Comment mettre en place un team building ?" class="read-more" href="https://sametmax.com/comment-mettre-en-place-un-team-building/" aria-label="Plus sur Comment mettre en place un team building ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2530
title: Définition : PLV
uri: Définition-PLV
url: https://sametmax.com/definition-plv/
content:
La PLV figure dans la liste des stratégies les plus efficace en matière de marketing. Généralement, la Publicité sur le Lieu de Vente (PLV) désigne ... <a title="Définition : PLV" class="read-more" href="https://sametmax.com/definition-plv/" aria-label="Plus sur Définition : PLV">Lire l'article</a>


feed_id: https://sametmax.com/?p=2580
title: Quelles sont les principales étapes de la chaîne de valeur ?
uri: Quelles-sont-les-principales-étapes-de-la-chaîne-de-valeur
url: https://sametmax.com/quelles-sont-les-principales-etapes-de-la-chaine-de-valeur/
content:
L’analyse de la chaîne de valeur est une étude qui vous permet d’identifier les activités et fonctions à travers lesquelles une entreprise crée de la ... <a title="Quelles sont les principales étapes de la chaîne de valeur ?" class="read-more" href="https://sametmax.com/quelles-sont-les-principales-etapes-de-la-chaine-de-valeur/" aria-label="Plus sur Quelles sont les principales étapes de la chaîne de valeur ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2703
title: Comment se réinscrire à Pôle Emploi après une formation ?
uri: Comment-se-réinscrire-à-Pôle-Emploi-après-une-formation
url: https://sametmax.com/comment-se-reinscrire-a-pole-emploi-apres-une-formation/
content:
Les chômeurs qui souhaitent signer leur contrat de travail ou s&#8217;inscrire à Pôle Emploi pour bénéficier des allocations doivent respecter certaines démarches. Mais que se ... <a title="Comment se réinscrire à Pôle Emploi après une formation ?" class="read-more" href="https://sametmax.com/comment-se-reinscrire-a-pole-emploi-apres-une-formation/" aria-label="Plus sur Comment se réinscrire à Pôle Emploi après une formation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2591
title: Stratégie de retargeting : comment la mettre en place ?
uri: Stratégie-de-retargeting-comment-la-mettre-en-place
url: https://sametmax.com/strategie-de-retargeting/
content:
À part le marketing automation, pour augmenter la vente sur votre site web e-commerce, l’application d’une stratégie de retargeting ou remarketing pourra certainement être très ... <a title="Stratégie de retargeting : comment la mettre en place ?" class="read-more" href="https://sametmax.com/strategie-de-retargeting/" aria-label="Plus sur Stratégie de retargeting : comment la mettre en place ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2684
title: Comment faire un mapping concurrentiel ?
uri: Comment-faire-un-mapping-concurrentiel
url: https://sametmax.com/comment-faire-un-mapping-concurrentiel/
content:
Dans le monde digital, la plupart des entreprises qui ont migré leur activité sur le web proposent aux internautes sur le marché différents services et ... <a title="Comment faire un mapping concurrentiel ?" class="read-more" href="https://sametmax.com/comment-faire-un-mapping-concurrentiel/" aria-label="Plus sur Comment faire un mapping concurrentiel ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2690
title: Développeur Full Stack : Définition
uri: Développeur-Full-Stack-Définition
url: https://sametmax.com/developpeur-full-stack-definition/
content:
Le terme « Full Stack » est récemment apparu dans le monde des développeurs et l&#8217;utilisation de ce terme a pris de l&#8217;importance ces dernières années. Pour ... <a title="Développeur Full Stack : Définition" class="read-more" href="https://sametmax.com/developpeur-full-stack-definition/" aria-label="Plus sur Développeur Full Stack : Définition">Lire l'article</a>


feed_id: https://sametmax.com/?p=2694
title: Comment modifier un PDF sans Acrobat ?
uri: Comment-modifier-un-PDF-sans-Acrobat
url: https://sametmax.com/modifier-un-pdf-sans-acrobat/
content:
Un format PDF est très pratique pour partager des documents de tout type, mais pas toujours facile à modifier. Heureusement, il existe plusieurs façons d&#8217;éditer ... <a title="Comment modifier un PDF sans Acrobat ?" class="read-more" href="https://sametmax.com/modifier-un-pdf-sans-acrobat/" aria-label="Plus sur Comment modifier un PDF sans Acrobat ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2847
title: Avis sur Savage Note : Le service de rédaction par excellence ?
uri: Avis-sur-Savage-Note-Le-service-de-rédaction-par-excellence
url: https://sametmax.com/avis-savage-note/
content:
Si vous êtes dans l&#8217;édition de site depuis plus d&#8217;un an, vous connaissez très certainement TonTexte, une plateforme de rédaction sous forme de pack « prêt ... <a title="Avis sur Savage Note : Le service de rédaction par excellence ?" class="read-more" href="https://sametmax.com/avis-savage-note/" aria-label="Plus sur Avis sur Savage Note : Le service de rédaction par excellence ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2743
title: Quels sont les logiciel permettant de créer un diaporama de présentation ?
uri: Quels-sont-les-logiciel-permettant-de-créer-un-diaporama-de-présenta
url: https://sametmax.com/quels-sont-les-logiciel-permettant-de-creer-un-diaporama-de-presentation/
content:
Aujourd’hui, les présentations sont très courantes pour beaucoup d&#8217;activités telles que le travail scolaire ou professionnel. Il est donc important d’avoir des outils adéquats pour ... <a title="Quels sont les logiciel permettant de créer un diaporama de présentation ?" class="read-more" href="https://sametmax.com/quels-sont-les-logiciel-permettant-de-creer-un-diaporama-de-presentation/" aria-label="Plus sur Quels sont les logiciel permettant de créer un diaporama de présentation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2700
title: Comment devenir testeur de produits et en tirer profit ?
uri: Comment-devenir-testeur-de-produits-et-en-tirer-profit
url: https://sametmax.com/comment-devenir-testeur-de-produits/
content:
Vous avez probablement déjà entendu parler des tests rémunérés à domicile. De plus en plus, les marques l’utilisent comme méthode pour créer des produits améliorés ... <a title="Comment devenir testeur de produits et en tirer profit ?" class="read-more" href="https://sametmax.com/comment-devenir-testeur-de-produits/" aria-label="Plus sur Comment devenir testeur de produits et en tirer profit ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2708
title: Comment acheter des abonnés sur Instagram ?
uri: Comment-acheter-des-abonnés-sur-Instagram
url: https://sametmax.com/comment-acheter-des-abonnes-sur-instagram/
content:
Dans le monde d’aujourd’hui, il est devenu très courant d’acheter des followers Instagram pour améliorer sa présence en ligne. Avec une base d&#8217;abonnés plus large ... <a title="Comment acheter des abonnés sur Instagram ?" class="read-more" href="https://sametmax.com/comment-acheter-des-abonnes-sur-instagram/" aria-label="Plus sur Comment acheter des abonnés sur Instagram ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2861
title: Botify vs Seolyzer.io : quel outil SEO choisir pour votre site ?
uri: Botify-vs-Seolyzer-io-quel-outil-SEO-choisir-pour-votre-site
url: https://sametmax.com/botify-vs-seolyzer-io-quel-outil-seo-choisir-pour-votre-site/
content:
Certains outils sont indispensables aux webmasters lorsqu&#8217;il s&#8217;agit de rechercher des mots-clés et d&#8217;optimiser le référencement naturel (SEO) de leur site. Les principaux outils d&#8217;analyse ... <a title="Botify vs Seolyzer.io : quel outil SEO choisir pour votre site ?" class="read-more" href="https://sametmax.com/botify-vs-seolyzer-io-quel-outil-seo-choisir-pour-votre-site/" aria-label="Plus sur Botify vs Seolyzer.io : quel outil SEO choisir pour votre site ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2767
title: Les étapes et leviers d’une démarche marketing
uri: Les-étapes-et-leviers-d-une-démarche-marketing
url: https://sametmax.com/demarche-marketing/
content:
Le marketing est un outil essentiel pour toute entreprise qui veut se démarquer et développer son activité. Mais pour que le marketing soit efficace, il ... <a title="Les étapes et leviers d&#8217;une démarche marketing" class="read-more" href="https://sametmax.com/demarche-marketing/" aria-label="Plus sur Les étapes et leviers d&#8217;une démarche marketing">Lire l'article</a>


feed_id: https://sametmax.com/?p=2732
title: Qu’est-ce qu’une zone de chalandise isométrique ?
uri: Qu-est-ce-qu-une-zone-de-chalandise-isométrique
url: https://sametmax.com/zone-de-chalandise-isometrique/
content:
Une zone de chalandise isométrique est une méthode personnalisée qui permet d&#8217;identifier et de regrouper les zones géographiques auxquelles se destine un produit ou un ... <a title="Qu&#8217;est-ce qu&#8217;une zone de chalandise isométrique ?" class="read-more" href="https://sametmax.com/zone-de-chalandise-isometrique/" aria-label="Plus sur Qu&#8217;est-ce qu&#8217;une zone de chalandise isométrique ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2746
title: Pourquoi je n’arrive pas à connecter mes écouteurs Bluetooth ?
uri: Pourquoi-je-n-arrive-pas-à-connecter-mes-écouteurs-Bluetooth
url: https://sametmax.com/je-narrive-pas-a-connecter-mes-ecouteurs-bluetooth/
content:
Les écouteurs sans fil offrent une liberté et un confort d&#8217;utilisation inégalés. La technologie Bluetooth permet de se débarrasser des câbles qui relient les appareils ... <a title="Pourquoi je n&#8217;arrive pas à connecter mes écouteurs Bluetooth ?" class="read-more" href="https://sametmax.com/je-narrive-pas-a-connecter-mes-ecouteurs-bluetooth/" aria-label="Plus sur Pourquoi je n&#8217;arrive pas à connecter mes écouteurs Bluetooth ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2878
title: Quel est le rôle de la manutention dans l’entreprise ?
uri: Quel-est-le-rôle-de-la-manutention-dans-l-entreprise
url: https://sametmax.com/quel-est-le-role-de-la-manutention-dans-lentreprise/
content:
Si vous souhaitez que votre entreprise tourne comme sur des roulettes, il est essentiel de s&#8217;intéresser à l&#8217;aspect de la manutention. Pouvant être définie comme ... <a title="Quel est le rôle de la manutention dans l&#8217;entreprise ?" class="read-more" href="https://sametmax.com/quel-est-le-role-de-la-manutention-dans-lentreprise/" aria-label="Plus sur Quel est le rôle de la manutention dans l&#8217;entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2749
title: Les logiciel de traitement de texte gratuit pour votre ordinateur
uri: Les-logiciel-de-traitement-de-texte-gratuit-pour-votre-ordinateur
url: https://sametmax.com/les-logiciel-de-traitement-de-texte-gratuit-pour-votre-ordinateur/
content:
Un logiciel de traitement de texte est un outil essentiel pour créer et gérer des documents. Les utilisateurs peuvent éditer, enregistrer et partager facilement des ... <a title="Les logiciel de traitement de texte gratuit pour votre ordinateur" class="read-more" href="https://sametmax.com/les-logiciel-de-traitement-de-texte-gratuit-pour-votre-ordinateur/" aria-label="Plus sur Les logiciel de traitement de texte gratuit pour votre ordinateur">Lire l'article</a>


feed_id: https://sametmax.com/?p=2752
title: Les logiciels qui permettent d’automatiser des calculs dans un tableau
uri: Les-Logiciels-qui-permettent-d-automatiser-des-Calculs-dans-un-Table
url: https://sametmax.com/logiciels-qui-permettent-dautomatiser-des-calculs-dans-un-tableau/
content:
Dans le monde professionnel, il est fréquent de devoir effectuer des calculs complexes et récurrents. Pour cela, les logiciels spécialisés sous forme de tableur ou ... <a title="Les logiciels qui permettent d&#8217;automatiser des calculs dans un tableau" class="read-more" href="https://sametmax.com/logiciels-qui-permettent-dautomatiser-des-calculs-dans-un-tableau/" aria-label="Plus sur Les logiciels qui permettent d&#8217;automatiser des calculs dans un tableau">Lire l'article</a>


feed_id: https://sametmax.com/?p=2797
title: Les moyens de communication les plus efficaces pour une stratégie réussie
uri: Les-moyens-de-communication-les-plus-efficaces-pour-une-stratégie-ré
url: https://sametmax.com/moyen-de-communication/
content:
La communication est l&#8217;un des outils les plus importants pour les entreprises, car elle est à la base de toute relation commerciale. Elle peut être ... <a title="Les moyens de communication les plus efficaces pour une stratégie réussie" class="read-more" href="https://sametmax.com/moyen-de-communication/" aria-label="Plus sur Les moyens de communication les plus efficaces pour une stratégie réussie">Lire l'article</a>


feed_id: https://sametmax.com/?p=2792
title: Tout savoir sur le marketing relationnel
uri: Tout-savoir-sur-le-marketing-relationnel
url: https://sametmax.com/marketing-relationnel/
content:
Le marketing relationnel est une discipline qui se concentre sur la création et le développement durable des relations entre une marque, ses clients et ses ... <a title="Tout savoir sur le marketing relationnel" class="read-more" href="https://sametmax.com/marketing-relationnel/" aria-label="Plus sur Tout savoir sur le marketing relationnel">Lire l'article</a>


feed_id: https://sametmax.com/?p=2788
title: Qu’est-ce que le marketing opérationnel ?
uri: Qu-est-ce-que-le-marketing-opérationnel
url: https://sametmax.com/marketing-operationnel/
content:
Le marketing opérationnel est un terme qui est souvent confondu avec le marketing stratégique. La compréhension claire et précise de ces deux termes est cruciale ... <a title="Qu&#8217;est-ce que le marketing opérationnel ?" class="read-more" href="https://sametmax.com/marketing-operationnel/" aria-label="Plus sur Qu&#8217;est-ce que le marketing opérationnel ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2784
title: Quels sont les KPIs à prendre en compte dans sa stratégie marketing ?
uri: Quels-sont-les-KPIs-à-prendre-en-compte-dans-sa-stratégie-marketing
url: https://sametmax.com/kpi-marketing/
content:
Les Key Performance Indicators (KPIs) sont des indicateurs de performance très importants qui peuvent aider les entreprises à savoir si leur stratégie marketing est efficace ... <a title="Quels sont les KPIs à prendre en compte dans sa stratégie marketing ?" class="read-more" href="https://sametmax.com/kpi-marketing/" aria-label="Plus sur Quels sont les KPIs à prendre en compte dans sa stratégie marketing ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3046
title: Comment calculer le taux de croissance d’une matrice BCG ?
uri: Comment-calculer-le-taux-de-croissance-d-une-matrice-BCG
url: https://sametmax.com/comment-calculer-le-taux-de-croissance-dune-matrice-bcg/
content:
La matrice BCG est un outil d&#8217;analyse stratégique qui permet de classer les produits ou services d&#8217;une entreprise en fonction de leur part de marché ... <a title="Comment calculer le taux de croissance d&#8217;une matrice BCG ?" class="read-more" href="https://sametmax.com/comment-calculer-le-taux-de-croissance-dune-matrice-bcg/" aria-label="Plus sur Comment calculer le taux de croissance d&#8217;une matrice BCG ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2780
title: Exemples d’insight client pour une expérience unique
uri: Exemples-d-insight-client-pour-une-expérience-unique
url: https://sametmax.com/insight-communication-exemple/
content:
Aujourd’hui, les consommateurs sont confrontés à une multitude de produits et services et sont sollicités à travers des campagnes publicitaires omniprésentes. Pour se démarquer, les ... <a title="Exemples d&#8217;insight client pour une expérience unique" class="read-more" href="https://sametmax.com/insight-communication-exemple/" aria-label="Plus sur Exemples d&#8217;insight client pour une expérience unique">Lire l'article</a>


feed_id: https://sametmax.com/?p=2776
title: Inbound marketing : Définition et exemples concrets
uri: Inbound-marketing-Définition-et-exemples-concrets
url: https://sametmax.com/inbound-marketing-exemple/
content:
Le marketing digital évolue constamment et il est essentiel pour les entreprises de rester à la page. L’inbound marketing est une forme de marketing numérique ... <a title="Inbound marketing : Définition et exemples concrets" class="read-more" href="https://sametmax.com/inbound-marketing-exemple/" aria-label="Plus sur Inbound marketing : Définition et exemples concrets">Lire l'article</a>


feed_id: https://sametmax.com/?p=2763
title: Les principaux outils de communication interne pour les entreprises
uri: Les-principaux-outils-de-communication-interne-pour-les-entreprises
url: https://sametmax.com/communication-interne/
content:
Lorsque l’on parle de communication, il est très important de bien comprendre les différents types de communication et leurs spécificités. Chaque type de communication a ... <a title="Les principaux outils de communication interne pour les entreprises" class="read-more" href="https://sametmax.com/communication-interne/" aria-label="Plus sur Les principaux outils de communication interne pour les entreprises">Lire l'article</a>


feed_id: https://sametmax.com/?p=2825
title: Les 10 avantages du marketing digital pour votre stratégie d’entreprise
uri: Les-10-avantages-du-marketing-digital-pour-votre-stratégie-d-entrep
url: https://sametmax.com/10-avantages-du-marketing-digital-pour-votre-strategie-dentreprise/
content:
Le marketing digital est une forme de marketing qui utilise les technologies numériques, principalement Internet, pour promouvoir et vendre des produits ou services. Il fait ... <a title="Les 10 avantages du marketing digital pour votre stratégie d&#8217;entreprise" class="read-more" href="https://sametmax.com/10-avantages-du-marketing-digital-pour-votre-strategie-dentreprise/" aria-label="Plus sur Les 10 avantages du marketing digital pour votre stratégie d&#8217;entreprise">Lire l'article</a>


feed_id: https://sametmax.com/?p=3124
title: Pourquoi externaliser la comptabilité de son entreprise ?
uri: Pourquoi-externaliser-la-comptabilité-de-son-entreprise
url: https://sametmax.com/pourquoi-externaliser-la-comptabilite-de-son-entreprise/
content:
L&#8217;externalisation de la comptabilité est une pratique qui consiste à confier tout ou partie de la gestion comptable d&#8217;une entreprise à un prestataire externe spécialisé ... <a title="Pourquoi externaliser la comptabilité de son entreprise ?" class="read-more" href="https://sametmax.com/pourquoi-externaliser-la-comptabilite-de-son-entreprise/" aria-label="Plus sur Pourquoi externaliser la comptabilité de son entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3129
title: map(), filter() et reduce () ?
uri: map()-filter()-et-reduce-()
url: https://sametmax.com/map-filter-et-reduce/
content:
Article repris par les nouveaux propriétaires en hommage à l&#8217;ancien site de sametmax.com map(),&#160;filter()&#160;et&#160;reduce()&#160;sont des fonctions de traitement d’itérables typiques de la programmation fonctionnelle, qui&#160;ont ... <a title="map(), filter() et reduce () ?" class="read-more" href="https://sametmax.com/map-filter-et-reduce/" aria-label="Plus sur map(), filter() et reduce () ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3061
title: Quelle est la différence entre une analyse et un diagnostic stratégique ?
uri: Quelle-est-la-différence-entre-une-analyse-et-un-diagnostic-stratégi
url: https://sametmax.com/quelle-est-la-difference-entre-une-analyse-et-un-diagnostic-strategique/
content:
L&#8217;analyse et le diagnostic stratégique sont des termes qui sont souvent employés de manière interchangeable. Cependant, ils réfèrent à des concepts distincts liés à l&#8217;orientation ... <a title="Quelle est la différence entre une analyse et un diagnostic stratégique ?" class="read-more" href="https://sametmax.com/quelle-est-la-difference-entre-une-analyse-et-un-diagnostic-strategique/" aria-label="Plus sur Quelle est la différence entre une analyse et un diagnostic stratégique ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2771
title: Tout savoir sur le funnel marketing
uri: Tout-savoir-sur-le-funnel-marketing
url: https://sametmax.com/funnel-marketing/
content:
Le marketing est l&#8217;un des moteurs de croissance les plus puissants pour les entreprises et le funnel marketing, ou tunnel marketing, est une méthodologie qui ... <a title="Tout savoir sur le funnel marketing" class="read-more" href="https://sametmax.com/funnel-marketing/" aria-label="Plus sur Tout savoir sur le funnel marketing">Lire l'article</a>


feed_id: https://sametmax.com/?p=3055
title: Comment gagner de l’argent sur TikTok en 2023 ?
uri: Comment-gagner-de-l-argent-sur-TikTok-en-2023
url: https://sametmax.com/comment-gagner-de-largent-sur-tiktok-en-2023/
content:
TikTok est désormais l&#8217;une des applications les plus connues et les plus populaires au monde. Environ 800 millions de personnes utilisent actuellement l&#8217;application. Depuis longtemps, ... <a title="Comment gagner de l’argent sur TikTok en 2023 ?" class="read-more" href="https://sametmax.com/comment-gagner-de-largent-sur-tiktok-en-2023/" aria-label="Plus sur Comment gagner de l’argent sur TikTok en 2023 ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3065
title: Comment calculer un retour sur investissement d’une machine ?
uri: Comment-calculer-un-retour-sur-investissement-d-une-machine
url: https://sametmax.com/calculer-un-retour-sur-investissement-dune-machine/
content:
Le retour sur investissement (ROI) est un indicateur clé pour évaluer la rentabilité d&#8217;un investissement. Cela peut être particulièrement important lorsqu&#8217;il s&#8217;agit de l&#8217;achat d&#8217;une ... <a title="Comment calculer un retour sur investissement d&#8217;une machine ?" class="read-more" href="https://sametmax.com/calculer-un-retour-sur-investissement-dune-machine/" aria-label="Plus sur Comment calculer un retour sur investissement d&#8217;une machine ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3070
title: Comment améliorer son image de marque ?
uri: Comment-améliorer-son-image-de-marque
url: https://sametmax.com/comment-ameliorer-son-image-de-marque/
content:
L&#8217;image de marque, ou branding, est la manière dont les entreprises et les organisations sont perçues par le public. Cette perception peut être créée de ... <a title="Comment améliorer son image de marque ?" class="read-more" href="https://sametmax.com/comment-ameliorer-son-image-de-marque/" aria-label="Plus sur Comment améliorer son image de marque ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3090
title: Quels sont les facteurs qui influencent le comportement d’achat ?
uri: Quels-sont-les-facteurs-qui-influencent-le-comportement-d-achat
url: https://sametmax.com/quels-sont-les-facteurs-qui-influencent-le-comportement-d-achat/
content:
Votre service ou votre produit n’a aucun sens si personne ne veut l’acheter et, plus important encore, si ces derniers ont un pouvoir d’achat considérable. ... <a title="Quels sont les facteurs qui influencent le comportement d&#8217;achat ?" class="read-more" href="https://sametmax.com/quels-sont-les-facteurs-qui-influencent-le-comportement-d-achat/" aria-label="Plus sur Quels sont les facteurs qui influencent le comportement d&#8217;achat ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3102
title: Comment définir une stratégie d’innovation ?
uri: Comment-définir-une-stratégie-d-innovation
url: https://sametmax.com/strategie-dinnovation/
content:
L&#8217;innovation est la clé du succès pour beaucoup d&#8217;entreprises. Pour de nombreuses organisations, il est essentiel d&#8217;avoir une stratégie d&#8217;innovation pour rester en tête de ... <a title="Comment définir une stratégie d&#8217;innovation ?" class="read-more" href="https://sametmax.com/strategie-dinnovation/" aria-label="Plus sur Comment définir une stratégie d&#8217;innovation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3115
title: Comment fonctionne le Trade marketing ?
uri: Comment-fonctionne-le-Trade-marketing
url: https://sametmax.com/comment-fonctionne-le-trade-marketing/
content:
Le trade marketing est une approche du marketing interentreprises qui consiste à comprendre les intérêts communs des producteurs et des distributeurs, afin de créer des ... <a title="Comment fonctionne le Trade marketing ?" class="read-more" href="https://sametmax.com/comment-fonctionne-le-trade-marketing/" aria-label="Plus sur Comment fonctionne le Trade marketing ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=2857
title: Fermeture d’entreprise : quel organisme pour débarrasser vos meubles ?
uri: Fermeture-d-entreprise-quel-organisme-pour-débarrasser-vos-meuble
url: https://sametmax.com/fermeture-dentreprise-quel-organisme-pour-debarrasser-vos-meubles/
content:
Il n’y a pas que les particuliers qui ont besoin d’un service de débarras. Les entreprises peuvent également avoir besoin de vider un local professionnel. ... <a title="Fermeture d’entreprise : quel organisme pour débarrasser vos meubles ?" class="read-more" href="https://sametmax.com/fermeture-dentreprise-quel-organisme-pour-debarrasser-vos-meubles/" aria-label="Plus sur Fermeture d’entreprise : quel organisme pour débarrasser vos meubles ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3316
title: Benchmark digital : quel intérêt dans une stratégie marketing ?
uri: Benchmark-digital-quel-intérêt-dans-une-stratégie-marketing
url: https://sametmax.com/benchmark-digital-quel-interet-dans-une-strategie-marketing/
content:
Le benchmark numérique ou digital est une étape importante dans le lancement de tout projet numérique. Elle vous permet d&#8217;identifier les tendances actuelles du marché, ... <a title="Benchmark digital : quel intérêt dans une stratégie marketing  ?" class="read-more" href="https://sametmax.com/benchmark-digital-quel-interet-dans-une-strategie-marketing/" aria-label="Plus sur Benchmark digital : quel intérêt dans une stratégie marketing  ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3137
title: Pourquoi faire du marketing automation ?
uri: Pourquoi-faire-du-marketing-automation
url: https://sametmax.com/pourquoi-faire-du-marketing-automation/
content:
L&#8217;automatisation du marketing est devenue un outil essentiel pour les entreprises qui cherchent à maximiser l&#8217;efficacité et la rentabilité dans une démarche marketing. Grâce à ... <a title="Pourquoi faire du marketing automation ?" class="read-more" href="https://sametmax.com/pourquoi-faire-du-marketing-automation/" aria-label="Plus sur Pourquoi faire du marketing automation ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3149
title: Quels sont les 3 piliers du SEO ?
uri: Quels-sont-les-3-piliers-du-SEO
url: https://sametmax.com/quels-sont-les-3-piliers-du-seo/
content:
L&#8217;optimisation des moteurs de recherche (SEO) est un levier d&#8217;acquisition intéréssant pour les entreprises qui souhaitent accroître leur visibilité dans les résultats des moteurs de ... <a title="Quels sont les 3 piliers du SEO ?" class="read-more" href="https://sametmax.com/quels-sont-les-3-piliers-du-seo/" aria-label="Plus sur Quels sont les 3 piliers du SEO ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3162
title: Qu’est-ce que l’acte d’achat en marketing ?
uri: Qu-est-ce-que-l-acte-d-achat-en-marketing
url: https://sametmax.com/quest-ce-que-lacte-dachat-en-marketing/
content:
L&#8217;acte d&#8217;achat est une étape critique du processus de décision d&#8217;achat du consommateur, et il peut avoir un impact majeur sur la réussite de la ... <a title="Qu&#8217;est-ce que l&#8217;acte d&#8217;achat en marketing ?" class="read-more" href="https://sametmax.com/quest-ce-que-lacte-dachat-en-marketing/" aria-label="Plus sur Qu&#8217;est-ce que l&#8217;acte d&#8217;achat en marketing ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3181
title: Comment élaborer une stratégie de niche ?
uri: Comment-élaborer-une-stratégie-de-niche
url: https://sametmax.com/comment-elaborer-une-strategie-de-niche/
content:
Une stratégie de niche est une démarche marketing hautement spécialisée du marketing qui vise à cibler un marché très restreint et spécifique. Cette stratégie marketing ... <a title="Comment élaborer une stratégie de niche ?" class="read-more" href="https://sametmax.com/comment-elaborer-une-strategie-de-niche/" aria-label="Plus sur Comment élaborer une stratégie de niche ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3185
title: Quels sont les 3 types de motivations d’achat ?
uri: Quels-sont-les-3-types-de-motivations-d-achat
url: https://sametmax.com/3-types-de-motivations-dachat/
content:
Comprendre les principaux moteurs des décisions des consommateurs pour élaborer des arguments de vente efficaces. Il existe trois principaux types de motivations d&#8217;achat : oblatives, ... <a title="Quels sont les 3 types de motivations d&#8217;achat ?" class="read-more" href="https://sametmax.com/3-types-de-motivations-dachat/" aria-label="Plus sur Quels sont les 3 types de motivations d&#8217;achat ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3191
title: Quelles sont les composantes de l’environnement marketing d’une entreprise ?
uri: Quelles-sont-les-composantes-de-l-environnement-marketing-d-une-en
url: https://sametmax.com/composantes-environnement-marketing/
content:
L&#8217;environnement marketing d&#8217;une entreprise se compose de facteurs internes et de forces externes qui ont un impact sur son fonctionnement. Tous les éléments de l&#8217;environnement ... <a title="Quelles sont les composantes de l&#8217;environnement marketing d&#8217;une entreprise ?" class="read-more" href="https://sametmax.com/composantes-environnement-marketing/" aria-label="Plus sur Quelles sont les composantes de l&#8217;environnement marketing d&#8217;une entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3199
title: Lead nurturing : c’est quoi ?
uri: Lead-nurturing-c-est-quoi
url: https://sametmax.com/lead-nurturing-cest-quoi/
content:
Le lead nurturing est une stratégie efficace que les entreprises utilisent pour établir des relations avec des clients potentiels et les accompagner tout au long ... <a title="Lead nurturing : c&#8217;est quoi ?" class="read-more" href="https://sametmax.com/lead-nurturing-cest-quoi/" aria-label="Plus sur Lead nurturing : c&#8217;est quoi ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3214
title: Comment auditer le processus commercial ?
uri: Comment-auditer-le-processus-commercial
url: https://sametmax.com/comment-auditer-le-processus-commercial/
content:
L&#8217;audit du processus de vente est un élément important de toute entreprise. Il vous permet d&#8217;évaluer l&#8217;efficacité et l&#8217;efficience de vos opérations de vente et ... <a title="Comment auditer le processus commercial ?" class="read-more" href="https://sametmax.com/comment-auditer-le-processus-commercial/" aria-label="Plus sur Comment auditer le processus commercial ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3240
title: Quelles sont les principales caractéristiques du marketing d’influence ?
uri: Quelles-sont-les-principales-caractéristiques-du-marketing-d-influe
url: https://sametmax.com/quelles-sont-les-principales-caracteristiques-du-marketing-dinfluence/
content:
Le marketing d&#8217;influence est un outil puissant permettant aux entreprises d&#8217;atteindre leur public cible. En s&#8217;associant avec des influenceurs, les marques peuvent exploiter l&#8217;influence de ... <a title="Quelles sont les principales caractéristiques du marketing d&#8217;influence ?" class="read-more" href="https://sametmax.com/quelles-sont-les-principales-caracteristiques-du-marketing-dinfluence/" aria-label="Plus sur Quelles sont les principales caractéristiques du marketing d&#8217;influence ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3262
title: Combien coute la production d’un livre blanc ?
uri: Combien-coute-la-production-d-un-livre-blanc
url: https://sametmax.com/combien-coute-la-production-dun-livre-blanc/
content:
La production d&#8217;un livre blanc est un moyen efficace de démontrer votre expertise et de générer des prospects pour votre entreprise. Mais combien coûte la ... <a title="Combien coute la production d&#8217;un livre blanc ?" class="read-more" href="https://sametmax.com/combien-coute-la-production-dun-livre-blanc/" aria-label="Plus sur Combien coute la production d&#8217;un livre blanc ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3271
title: Comment analyser une campagne Google Ads ?
uri: Comment-analyser-une-campagne-Google-Ads
url: https://sametmax.com/comment-analyser-une-campagne-google-ads/
content:
L&#8217;analyse d&#8217;une campagne Google Ads peut être un moyen de communication intimidant. Avec autant de variables à prendre en compte et de paramètres à suivre, ... <a title="Comment analyser une campagne Google Ads ?" class="read-more" href="https://sametmax.com/comment-analyser-une-campagne-google-ads/" aria-label="Plus sur Comment analyser une campagne Google Ads ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3366
title: Que manger au bureau ?
uri: Que-manger-au-bureau
url: https://sametmax.com/que-manger-au-bureau/
content:
Manger au bureau peut parfois être un défi, surtout lorsque l&#8217;on manque de temps et d&#8217;idées. Pourtant, il est essentiel de bien se nourrir afin ... <a title="Que manger au bureau ?" class="read-more" href="https://sametmax.com/que-manger-au-bureau/" aria-label="Plus sur Que manger au bureau ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3290
title: Définir son persona marketing en 5 étapes simples
uri: Définir-son-persona-marketing-en-5-étapes-simples
url: https://sametmax.com/le-persona-marketing-en-5-etapes-simples/
content:
Différentes techniques de marketing permettent à une entreprise de développer sa marque et d’améliorer ses résultats commerciaux. Identifier son client cible fait partie d’une stratégie ... <a title="Définir son persona marketing en 5 étapes simples" class="read-more" href="https://sametmax.com/le-persona-marketing-en-5-etapes-simples/" aria-label="Plus sur Définir son persona marketing en 5 étapes simples">Lire l'article</a>


feed_id: https://sametmax.com/?p=3297
title: Combien rapporte 1 million de vues sur Snapchat ?
uri: Combien-rapporte-1-million-de-vues-sur-Snapchat
url: https://sametmax.com/combien-rapporte-1-million-de-vues-sur-snapchat/
content:
Snapchat est une application de partage de médias et de messages éphémères qui compte actuellement plus de 300 millions d&#8217;utilisateurs actifs par mois. Dans un ... <a title="Combien rapporte 1 million de vues sur Snapchat ?" class="read-more" href="https://sametmax.com/combien-rapporte-1-million-de-vues-sur-snapchat/" aria-label="Plus sur Combien rapporte 1 million de vues sur Snapchat ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3302
title: Comment faire un sommaire sur Word ?
uri: Comment-faire-un-sommaire-sur-Word
url: https://sametmax.com/comment-faire-un-sommaire-sur-word/
content:
La création d&#8217;une table des matières ou d&#8217;un sommaire sur Microsoft Word est une tâche facile. Elle peut vous aider à organiser rapidement votre document ... <a title="Comment faire un sommaire sur Word ?" class="read-more" href="https://sametmax.com/comment-faire-un-sommaire-sur-word/" aria-label="Plus sur Comment faire un sommaire sur Word ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3327
title: Stratégie Marketing : définitions, exemples de stratégies réussies
uri: Stratégie-Marketing-définitions-exemples-de-stratégies-réussies
url: https://sametmax.com/strategie-marketing-definitions-et-exemple/
content:
Une stratégie marketing vise à atteindre les objectifs d’une entreprise en termes de notoriété et de conversion. Plusieurs actions sont mises en œuvre pour qu’un ... <a title="Stratégie Marketing : définitions, exemples de stratégies réussies" class="read-more" href="https://sametmax.com/strategie-marketing-definitions-et-exemple/" aria-label="Plus sur Stratégie Marketing : définitions, exemples de stratégies réussies">Lire l'article</a>


feed_id: https://sametmax.com/?p=3398
title: Comment utiliser ChatGPT : un guide complet
uri: Comment-utiliser-ChatGPT-un-guide-complet
url: https://sametmax.com/comment-utiliser-chatgpt-un-guide-complet/
content:
ChatGPT est une intelligence artificielle conversationnelle avancée, développée par la société OpenAI, qui peut être utilisée pour accomplir une multitude de tâches. Que vous cherchiez ... <a title="Comment utiliser ChatGPT : un guide complet" class="read-more" href="https://sametmax.com/comment-utiliser-chatgpt-un-guide-complet/" aria-label="Plus sur Comment utiliser ChatGPT : un guide complet">Lire l'article</a>


feed_id: https://sametmax.com/?p=3402
title: Comment avoir des abonnés sur TikTok ?
uri: Comment-avoir-des-abonnés-sur-TikTok
url: https://sametmax.com/comment-avoir-des-abonnes-sur-tiktok/
content:
Vous êtes fan de la plateforme TikTok et souhaitez augmenter votre nombre d&#8217;abonnés pour gagner en popularité ? Vous êtes au bon endroit ! Dans ... <a title="Comment avoir des abonnés sur TikTok ?" class="read-more" href="https://sametmax.com/comment-avoir-des-abonnes-sur-tiktok/" aria-label="Plus sur Comment avoir des abonnés sur TikTok ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3408
title: Les 10 meilleures raisons de se lancer dans l’entrepreneuriat
uri: Les-10-meilleures-raisons-de-se-lancer-dans-l-entrepreneuriat
url: https://sametmax.com/les-10-meilleures-raisons-de-se-lancer-dans-lentrepreneuriat/
content:
Décider d&#8217;entreprendre est une étape importante&#160;et passionnante dans la vie d&#8217;une personne. Il existe de nombreuses raisons pour lesquelles quelqu&#8217;un peut choisir cette voie, mais ... <a title="Les 10 meilleures raisons de se lancer dans l&#8217;entrepreneuriat" class="read-more" href="https://sametmax.com/les-10-meilleures-raisons-de-se-lancer-dans-lentrepreneuriat/" aria-label="Plus sur Les 10 meilleures raisons de se lancer dans l&#8217;entrepreneuriat">Lire l'article</a>


feed_id: https://sametmax.com/?p=3412
title: Comment choisir une salle pour un séminaire à Paris ?
uri: Comment-choisir-une-salle-pour-un-séminaire-à-Paris
url: https://sametmax.com/comment-choisir-une-salle-pour-un-seminaire-a-paris/
content:
Organiser un événement professionnel dans la capitale française peut sembler intimidant. Cependant, il existe une variété d&#8217;options pour la location de salles de réunion, séminaires ... <a title="Comment choisir une salle pour un séminaire à Paris ?" class="read-more" href="https://sametmax.com/comment-choisir-une-salle-pour-un-seminaire-a-paris/" aria-label="Plus sur Comment choisir une salle pour un séminaire à Paris ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3416
title: Décorez vos bureaux pour un environnement de travail inspirant
uri: Décorez-vos-bureaux-pour-un-environnement-de-travail-inspirant
url: https://sametmax.com/decorez-vos-bureaux-pour-un-environnement-de-travail-inspirant/
content:
La décoration des bureaux est essentielle pour créer un espace de travail agréable et stimulant. Un bureau bien aménagé peut favoriser la créativité, la productivité ... <a title="Décorez vos bureaux pour un environnement de travail inspirant" class="read-more" href="https://sametmax.com/decorez-vos-bureaux-pour-un-environnement-de-travail-inspirant/" aria-label="Plus sur Décorez vos bureaux pour un environnement de travail inspirant">Lire l'article</a>


feed_id: https://sametmax.com/?p=3425
title: Les constructions modulaires pour les entreprises : une solution flexible et économique
uri: Les-constructions-modulaires-pour-les-entreprises-une-solution-flexi
url:
https://sametmax.com/les-constructions-modulaires-pour-les-entreprises-une-solution-flexible-et-economique/

content:
Dans un monde où la flexibilité et l&#8217;adaptabilité sont devenues cruciales pour la réussite des entreprises, les constructions modulaires offrent une alternative intéressante aux méthodes ... <a title="Les constructions modulaires pour les entreprises : une solution flexible et économique" class="read-more" href="https://sametmax.com/les-constructions-modulaires-pour-les-entreprises-une-solution-flexible-et-economique/" aria-label="Plus sur Les constructions modulaires pour les entreprises : une solution flexible et économique">Lire l'article</a>


feed_id: https://sametmax.com/?p=3429
title: Les compétences clés d’un expert-comptable et leur importance pour les entreprises
uri: Les-compétences-clés-d-un-expert-comptable-et-leur-importance-pour
url:
https://sametmax.com/les-competences-cles-dun-expert-comptable-et-leur-importance-pour-les-entreprises/

content:
Dans le monde des affaires, le rôle de l&#8217;expert-comptable est primordial, car il apporte une assistance précieuse aux entreprises dans la gestion de leurs finances ... <a title="Les compétences clés d&#8217;un expert-comptable et leur importance pour les entreprises" class="read-more" href="https://sametmax.com/les-competences-cles-dun-expert-comptable-et-leur-importance-pour-les-entreprises/" aria-label="Plus sur Les compétences clés d&#8217;un expert-comptable et leur importance pour les entreprises">Lire l'article</a>


feed_id: https://sametmax.com/?p=3434
uri: Se-former-à-la-gestion-des-services-informatiques-développer-ses-c
title:
Se former à la gestion des services informatiques : développer ses compétences pour un secteur en pleine croissance

url:
https://sametmax.com/se-former-a-la-gestion-des-services-informatiques-developper-ses-competences-pour-un-secteur-en-pleine-croissance/

content:
La gestion des services informatiques est devenue un élément clé dans le succès et la pérennité des entreprises. Dans cet univers technologique en constante évolution, ... <a title="Se former à la gestion des services informatiques : développer ses compétences pour un secteur en pleine croissance" class="read-more" href="https://sametmax.com/se-former-a-la-gestion-des-services-informatiques-developper-ses-competences-pour-un-secteur-en-pleine-croissance/" aria-label="Plus sur Se former à la gestion des services informatiques : développer ses compétences pour un secteur en pleine croissance">Lire l'article</a>


feed_id: https://sametmax.com/?p=3438
title: Quels sont les métiers qui utilisent le logiciel AutoCAD ?
uri: Quels-sont-les-métiers-qui-utilisent-le-logiciel-AutoCAD
url: https://sametmax.com/quels-sont-les-metiers-qui-utilisent-le-logiciel-autocad/
content:
AutoCAD, le logiciel de conception assistée par ordinateur, s&#8217;est imposé comme un outil révolutionnaire dans différentes industries. Cela, depuis plusieurs décennies. Comment est-il utilisé dans ... <a title="Quels sont les métiers qui utilisent le logiciel AutoCAD ?" class="read-more" href="https://sametmax.com/quels-sont-les-metiers-qui-utilisent-le-logiciel-autocad/" aria-label="Plus sur Quels sont les métiers qui utilisent le logiciel AutoCAD ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3443
title: LinkedIn : 3 façons de pousser les internautes à interagir avec vos posts
uri: LinkedIn-3-façons-de-pousser-les-internautes-à-interagir-avec-vos
url: https://sametmax.com/linkedin-3-facons-de-pousser-les-internautes-a-interagir-avec-vos-posts/
content:
LinkedIn est le réseau social professionnel par excellence. Il vous permet de partager votre expertise, de promouvoir votre activité ou de trouver des opportunités de ... <a title="LinkedIn : 3 façons de pousser les internautes à interagir avec vos posts" class="read-more" href="https://sametmax.com/linkedin-3-facons-de-pousser-les-internautes-a-interagir-avec-vos-posts/" aria-label="Plus sur LinkedIn : 3 façons de pousser les internautes à interagir avec vos posts">Lire l'article</a>


feed_id: https://sametmax.com/?p=3448
title: Comment partager votre passion en vidéo avec vos followers ?
uri: Comment-partager-votre-passion-en-vidéo-avec-vos-followers
url: https://sametmax.com/comment-partager-votre-passion-en-video-avec-vos-followers/
content:
Les réseaux sociaux fournissent de nombreuses opportunités. D&#8217;ailleurs, de plus en plus de personnes les utilisent de nos jours pour se faire connaître et surtout ... <a title="Comment partager votre passion en vidéo avec vos followers ?" class="read-more" href="https://sametmax.com/comment-partager-votre-passion-en-video-avec-vos-followers/" aria-label="Plus sur Comment partager votre passion en vidéo avec vos followers ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3452
title: Portage salarial : les réponses aux questions les plus fréquentes
uri: Portage-salarial-les-réponses-aux-questions-les-plus-fréquentes
url: https://sametmax.com/portage-salarial-les-reponses-aux-questions-les-plus-frequentes/
content:
Le portage salarial est devenu un choix de plus en plus populaire parmi les professionnels indépendants à la recherche d&#8217;une alternative entre l&#8217;emploi traditionnel et ... <a title="Portage salarial : les réponses aux questions les plus fréquentes" class="read-more" href="https://sametmax.com/portage-salarial-les-reponses-aux-questions-les-plus-frequentes/" aria-label="Plus sur Portage salarial : les réponses aux questions les plus fréquentes">Lire l'article</a>


feed_id: https://sametmax.com/?p=3456
title: Les meilleures applications avec des fonctionnalités gratuites
uri: Les-meilleures-applications-avec-des-fonctionnalités-gratuites
url: https://sametmax.com/les-meilleures-applications-avec-des-fonctionnalites-gratuites/
content:
Sur le web ou directement sur les bibliothèques de téléchargement mobile, nombreuses sont les applications à proposer des fonctions payantes et gratuites à la fois. ... <a title="Les meilleures applications avec des fonctionnalités gratuites" class="read-more" href="https://sametmax.com/les-meilleures-applications-avec-des-fonctionnalites-gratuites/" aria-label="Plus sur Les meilleures applications avec des fonctionnalités gratuites">Lire l'article</a>


feed_id: https://sametmax.com/?p=3466
title: Devenez éducateur canin : quelles qualités font un bon professionnel ?
uri: Devenez-éducateur-canin-quelles-qualités-font-un-bon-professionnel
url: https://sametmax.com/devenez-educateur-canin-quelles-qualites-font-un-bon-professionnel/
content:
L&#8217;éducation canine est une discipline passionnante qui exige bien plus qu&#8217;une simple affection pour nos amis à quatre pattes. Devenir un éducateur canin compétent et ... <a title="Devenez éducateur canin : quelles qualités font un bon professionnel ?" class="read-more" href="https://sametmax.com/devenez-educateur-canin-quelles-qualites-font-un-bon-professionnel/" aria-label="Plus sur Devenez éducateur canin : quelles qualités font un bon professionnel ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3462
title: Le web marketing pour améliorer votre activité
uri: Le-web-marketing-pour-améliorer-votre-activité
url: https://sametmax.com/le-web-marketing-pour-ameliorer-votre-activite/
content:
Dans un contexte dans lequel la plupart des consommateurs recherchent des services en ligne, votre capacité à exploiter tout le potentiel du web marketing peut ... <a title="Le web marketing pour améliorer votre activité" class="read-more" href="https://sametmax.com/le-web-marketing-pour-ameliorer-votre-activite/" aria-label="Plus sur Le web marketing pour améliorer votre activité">Lire l'article</a>


feed_id: https://sametmax.com/?p=3471
title: Principales différences entre un téléphone jetable et un téléphone prépayé
uri: Principales-différences-entre-un-téléphone-jetable-et-un-téléphon
url: https://sametmax.com/principales-differences-entre-un-telephone-jetable-et-un-telephone-prepaye/
content:
Les téléphones mobiles sont devenus une partie incontournable de nos vies. Nous les utilisons tous les jours, par exemple, pour les SMS de vérification en ... <a title="Principales différences entre un téléphone jetable et un téléphone prépayé" class="read-more" href="https://sametmax.com/principales-differences-entre-un-telephone-jetable-et-un-telephone-prepaye/" aria-label="Plus sur Principales différences entre un téléphone jetable et un téléphone prépayé">Lire l'article</a>


feed_id: https://sametmax.com/?p=3476
title: Quel rôle joue l’ergonomie dans la productivité au travail
uri: Quel-rôle-joue-l-ergonomie-dans-la-productivité-au-travail
url: https://sametmax.com/quel-role-joue-lergonomie-dans-la-productivite-au-travail/
content:
Lorsque nous pensons à l&#8217;efficacité au travail, nous envisageons souvent des stratégies degestion du temps, des outils de collaboration ou des formations pour les employés. ... <a title="Quel rôle joue l’ergonomie dans la productivité au travail" class="read-more" href="https://sametmax.com/quel-role-joue-lergonomie-dans-la-productivite-au-travail/" aria-label="Plus sur Quel rôle joue l’ergonomie dans la productivité au travail">Lire l'article</a>


feed_id: https://sametmax.com/?p=3483
title: Télétravail : les solutions pour rester connecté avec vos collaborateurs
uri: Télétravail-les-solutions-pour-rester-connecté-avec-vos-collabora
url: https://sametmax.com/teletravail-les-solutions-pour-rester-connecte-avec-vos-collaborateurs/
content:
Dans le monde actuel, le télétravail est devenu une réalité pour de nombreuses entreprises. Cependant, il peut être difficile de rester connecté avec vos collaborateurs. ... <a title="Télétravail : les solutions pour rester connecté avec vos collaborateurs" class="read-more" href="https://sametmax.com/teletravail-les-solutions-pour-rester-connecte-avec-vos-collaborateurs/" aria-label="Plus sur Télétravail : les solutions pour rester connecté avec vos collaborateurs">Lire l'article</a>


feed_id: https://sametmax.com/?p=3488
title: Qu’est-ce que l’audit énergétique d’un bâtiment ?
uri: Qu-est-ce-que-l-audit-énergétique-d-un-bâtiment
url: https://sametmax.com/quest-ce-que-laudit-energetique-dun-batiment/
content:
Collecter les données, ne serait-ce pas là un défi de taille? En effet, c’est une étape cruciale pour l’audit. Il s’agit d’un processus méticuleux qui ... <a title="Qu&#8217;est-ce que l&#8217;audit énergétique d&#8217;un bâtiment ?" class="read-more" href="https://sametmax.com/quest-ce-que-laudit-energetique-dun-batiment/" aria-label="Plus sur Qu&#8217;est-ce que l&#8217;audit énergétique d&#8217;un bâtiment ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3494
title: Influenceur : sur quels réseaux acheter des likes ?
uri: Influenceur-sur-quels-réseaux-acheter-des-likes
url: https://sametmax.com/influenceur-sur-quels-reseaux-acheter-des-likes/
content:
L&#8217;avènement des réseaux sociaux a créé un nouveau paradigme dans la manière dont on interagit avec le monde numérique. Pour les influenceurs, l&#8217;engagement de leur ... <a title="Influenceur : sur quels réseaux acheter des likes ?" class="read-more" href="https://sametmax.com/influenceur-sur-quels-reseaux-acheter-des-likes/" aria-label="Plus sur Influenceur : sur quels réseaux acheter des likes ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3500
title: Une formation en informatique : que pouvez-vous attendre d’un BTS ?
uri: Une-formation-en-informatique-que-pouvez-vous-attendre-d-un-BTS
url: https://sametmax.com/une-formation-en-informatique-que-pouvez-vous-attendre-dun-bts/
content:
Suivre une formation en informatique, c&#8217;est vous mettre à niveau pour tirer profit du plein potentiel des nouvelles technologies. Les organismes dédiés s&#8217;adressent également aux ... <a title="Une formation en informatique : que pouvez-vous attendre d&#8217;un BTS ?" class="read-more" href="https://sametmax.com/une-formation-en-informatique-que-pouvez-vous-attendre-dun-bts/" aria-label="Plus sur Une formation en informatique : que pouvez-vous attendre d&#8217;un BTS ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3504
title: Les outils clés pour réussir votre projet de Business Intelligence
uri: Les-outils-clés-pour-réussir-votre-projet-de-Business-Intelligence
url: https://sametmax.com/les-outils-cles-pour-reussir-votre-projet-de-business-intelligence/
content:
Les entreprises génèrent de grandes quantités de données chaque jour. Chaque structure doit transformer ces données en informations précieuses pour prendre des décisions éclairées. Pour ... <a title="Les outils clés pour réussir votre projet de Business Intelligence" class="read-more" href="https://sametmax.com/les-outils-cles-pour-reussir-votre-projet-de-business-intelligence/" aria-label="Plus sur Les outils clés pour réussir votre projet de Business Intelligence">Lire l'article</a>


feed_id: https://sametmax.com/?p=3508
title: Apprendre le webdesign : en quoi ça consiste ?
uri: Apprendre-le-webdesign-en-quoi-ça-consiste
url: https://sametmax.com/apprendre-le-webdesign-en-quoi-ca-consiste/
content:
Le webdesign est une discipline en constante évolution qui joue un rôle essentiel dans la création d&#8217;expériences en ligne mémorables et efficaces. Pour les néophytes, ... <a title="Apprendre le webdesign : en quoi ça consiste ?" class="read-more" href="https://sametmax.com/apprendre-le-webdesign-en-quoi-ca-consiste/" aria-label="Plus sur Apprendre le webdesign : en quoi ça consiste ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3514
title: Comment mettre au point une campagne publicitaire Google ?
uri: Comment-mettre-au-point-une-campagne-publicitaire-Google
url: https://sametmax.com/comment-mettre-au-point-une-campagne-publicitaire-google/
content:
Vous souhaitez améliorer le positionnement de votre site internet sur les moteurs de recherche ? Alors, pourquoi ne pas mettre sur pied une campagne publicitaire ... <a title="Comment mettre au point une campagne publicitaire Google ?" class="read-more" href="https://sametmax.com/comment-mettre-au-point-une-campagne-publicitaire-google/" aria-label="Plus sur Comment mettre au point une campagne publicitaire Google ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3521
title: Amiez : C’est quoi ?
uri: Amiez-C-est-quoi
url: https://sametmax.com/amiez-le-site-de-rencontres-ludique-et-convivial/
content:
Dans notre monde moderne, faire de nouvelles rencontres et élargir son cercle d&#8217;amis peut s&#8217;avérer parfois difficile. C&#8217;est là que Amiez intervient. Le site a ... <a title="Amiez : C&#8217;est quoi ?" class="read-more" href="https://sametmax.com/amiez-le-site-de-rencontres-ludique-et-convivial/" aria-label="Plus sur Amiez : C&#8217;est quoi ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3527
title: Arkevia, la solution de stockage numérique sécurisée pour vos documents professionnels
uri: Arkevia-la-solution-de-stockage-numérique-sécurisée-pour-vos-docum
url:
https://sametmax.com/arkevia-la-solution-de-stockage-numerique-securisee-pour-vos-documents-professionnels/

content:
Dans un monde où le numérique prend une place de plus en plus importante, il devient essentiel de pouvoir compter sur des solutions de stockage ... <a title="Arkevia, la solution de stockage numérique sécurisée pour vos documents professionnels" class="read-more" href="https://sametmax.com/arkevia-la-solution-de-stockage-numerique-securisee-pour-vos-documents-professionnels/" aria-label="Plus sur Arkevia, la solution de stockage numérique sécurisée pour vos documents professionnels">Lire l'article</a>


feed_id: https://sametmax.com/?p=3530
title: Créer un sommaire PowerPoint engageant et professionnel
uri: Créer-un-sommaire-PowerPoint-engageant-et-professionnel
url: https://sametmax.com/creer-un-sommaire-powerpoint-engageant-et-professionnel/
content:
Dans le monde professionnel d&#8217;aujourd&#8217;hui, la capacité à exposer clairement ses idées et arguments revêt une importance capitale. Un élément crucial pour y parvenir est ... <a title="Créer un sommaire PowerPoint engageant et professionnel" class="read-more" href="https://sametmax.com/creer-un-sommaire-powerpoint-engageant-et-professionnel/" aria-label="Plus sur Créer un sommaire PowerPoint engageant et professionnel">Lire l'article</a>


feed_id: https://sametmax.com/?p=3534
title: Comment supprimer une page Word en toute simplicité
uri: Comment-supprimer-une-page-Word-en-toute-simplicité
url: https://sametmax.com/comment-supprimer-une-page-word-en-toute-simplicite/
content:
Avoir une maîtrise de Microsoft Word est essentiel pour la création et l&#8217;édition de documents. Bien sûr, il y a des options utiles et avancées ... <a title="Comment supprimer une page Word en toute simplicité" class="read-more" href="https://sametmax.com/comment-supprimer-une-page-word-en-toute-simplicite/" aria-label="Plus sur Comment supprimer une page Word en toute simplicité">Lire l'article</a>


feed_id: https://sametmax.com/?p=3537
title: Maîtriser l’utilisation des cases à cocher dans Excel
uri: Maîtriser-l-utilisation-des-cases-à-cocher-dans-Excel
url: https://sametmax.com/maitriser-lutilisation-des-cases-a-cocher-dans-excel/
content:
Les cases à cocher sont largement utilisées dans de nombreuses applications pour permettre aux utilisateurs de sélectionner ou de désélectionner une option. Excel n&#8217;est pas ... <a title="Maîtriser l&#8217;utilisation des cases à cocher dans Excel" class="read-more" href="https://sametmax.com/maitriser-lutilisation-des-cases-a-cocher-dans-excel/" aria-label="Plus sur Maîtriser l&#8217;utilisation des cases à cocher dans Excel">Lire l'article</a>


feed_id: https://sametmax.com/?p=3555
title: Ouverture d’une franchise de salon de beauté : les avantages et les inconvénients
uri: Ouverture-d-une-franchise-de-salon-de-beauté-les-avantages-et-les
url:
https://sametmax.com/ouverture-dune-franchise-de-salon-de-beaute-les-avantages-et-les-inconvenients/

content:
L&#8217;industrie de la beauté est en constante évolution, attirant des entrepreneurs avides de créer leur propre espace de bien-être. Parmi les nombreuses options qui s&#8217;offrent ... <a title="Ouverture d&#8217;une franchise de salon de beauté : les avantages et les inconvénients" class="read-more" href="https://sametmax.com/ouverture-dune-franchise-de-salon-de-beaute-les-avantages-et-les-inconvenients/" aria-label="Plus sur Ouverture d&#8217;une franchise de salon de beauté : les avantages et les inconvénients">Lire l'article</a>


feed_id: https://sametmax.com/?p=3551
title: WordPress : comment pratiquer le référencement de votre site vitrine ?
uri: WordPress-comment-pratiquer-le-référencement-de-votre-site-vitrine
url: https://sametmax.com/wordpress-comment-pratiquer-le-referencement-de-votre-site-vitrine/
content:
WordPress est l&#8217;un des outils de gestion de contenu les plus utilisés pour la création de sites web. Pour maximiser l&#8217;impact de votre site vitrine, ... <a title="WordPress : comment pratiquer le référencement de votre site vitrine ?" class="read-more" href="https://sametmax.com/wordpress-comment-pratiquer-le-referencement-de-votre-site-vitrine/" aria-label="Plus sur WordPress : comment pratiquer le référencement de votre site vitrine ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3571
title: Déclaration de TVA et travailleur indépendant : comment vous y prendre ?
uri: Déclaration-de-TVA-et-travailleur-indépendant-comment-vous-y-prend
url: https://sametmax.com/declaration-de-tva-et-travailleur-independant-comment-vous-y-prendre/
content:
En votre qualité de travailleur indépendant, il est obligatoire de soumettre régulièrement une déclaration de TVA. Celle-ci fait un récapitulatif de la taxe perçue à ... <a title="Déclaration de TVA et travailleur indépendant : comment vous y prendre ?" class="read-more" href="https://sametmax.com/declaration-de-tva-et-travailleur-independant-comment-vous-y-prendre/" aria-label="Plus sur Déclaration de TVA et travailleur indépendant : comment vous y prendre ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3577
title: 3 étapes clés de la création d’un site internet
uri: 3-étapes-clés-de-la-création-d-un-site-internet
url: https://sametmax.com/3-etapes-cles-de-la-creation-dun-site-internet/
content:
La création d&#8217;un site internet est une démarche structurée qui nécessite une réflexion préalable et un suivi rigoureux. Cette entreprise commence par la définition claire ... <a title="3 étapes clés de la création d&#8217;un site internet" class="read-more" href="https://sametmax.com/3-etapes-cles-de-la-creation-dun-site-internet/" aria-label="Plus sur 3 étapes clés de la création d&#8217;un site internet">Lire l'article</a>


feed_id: https://sametmax.com/?p=3584
title: Quelle est l’utilité d’un consultant en Business Intelligence ?
uri: Quelle-est-l-utilité-d-un-consultant-en-Business-Intelligence
url: https://sametmax.com/quelle-est-lutilite-dun-consultant-en-business-intelligence/
content:
Dans le monde des affaires moderne, l&#8217;accès à des informations pertinentes et exploitables est un avantage stratégique indéniable. C&#8217;est là qu&#8217;intervient un consultant en Business ... <a title="Quelle est l&#8217;utilité d&#8217;un consultant en Business Intelligence ?" class="read-more" href="https://sametmax.com/quelle-est-lutilite-dun-consultant-en-business-intelligence/" aria-label="Plus sur Quelle est l&#8217;utilité d&#8217;un consultant en Business Intelligence ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3543
title: Liste de voeux 2023 originaux
uri: Liste-de-voeux-2023-originaux
url: https://sametmax.com/liste-de-voeux-2023-originaux/
content:
La nouvelle année 2023 approche à grands pas, et il est temps de penser aux vœux que vous allez envoyer à vos proches, amis et ... <a title="Liste de voeux 2023 originaux" class="read-more" href="https://sametmax.com/liste-de-voeux-2023-originaux/" aria-label="Plus sur Liste de voeux 2023 originaux">Lire l'article</a>


feed_id: https://sametmax.com/?p=3545
title: Les secrets d’un slogan publicitaire réussi
uri: Les-secrets-d-un-slogan-publicitaire-réussi
url: https://sametmax.com/les-secrets-dun-slogan-publicitaire-reussi/
content:
Dans le monde de la publicité, un slogan publicitaire accrocheur et mémorable est essentiel pour capter l&#8217;attention du public et marquer les esprits. Comment concevoir ... <a title="Les secrets d&#8217;un slogan publicitaire réussi" class="read-more" href="https://sametmax.com/les-secrets-dun-slogan-publicitaire-reussi/" aria-label="Plus sur Les secrets d&#8217;un slogan publicitaire réussi">Lire l'article</a>


feed_id: https://sametmax.com/?p=3563
title: Le guide ultime des supports de stockage pour smartphones
uri: Le-guide-ultime-des-supports-de-stockage-pour-smartphones
url: https://sametmax.com/le-guide-ultime-des-supports-de-stockage-pour-smartphones/
content:
Les smartphones sont devenus des outils indispensables dans notre quotidien, et avec l&#8217;augmentation constante du nombre d&#8217;applications, de photos et de vidéos que nous avons ... <a title="Le guide ultime des supports de stockage pour smartphones" class="read-more" href="https://sametmax.com/le-guide-ultime-des-supports-de-stockage-pour-smartphones/" aria-label="Plus sur Le guide ultime des supports de stockage pour smartphones">Lire l'article</a>


feed_id: https://sametmax.com/?p=3566
title: Les philosophes français qui ont marqué l’histoire
uri: Les-philosophes-français-qui-ont-marqué-l-histoire
url: https://sametmax.com/les-philosophes-francais-qui-ont-marque-lhistoire/
content:
Dans cet article, nous allons explorer le monde fascinant des philosophes français, depuis leurs débuts en tant que penseurs de la Renaissance jusqu&#8217;à nos jours. ... <a title="Les philosophes français qui ont marqué l&#8217;histoire" class="read-more" href="https://sametmax.com/les-philosophes-francais-qui-ont-marque-lhistoire/" aria-label="Plus sur Les philosophes français qui ont marqué l&#8217;histoire">Lire l'article</a>


feed_id: https://sametmax.com/?p=3619
title: Présence numérique sur les réseaux sociaux : les supports d’information adéquats
uri: Présence-numérique-sur-les-réseaux-sociaux-les-supports-d-infor
url: https://sametmax.com/presence-numerique-sur-les-reseaux-sociaux-les-supports-dinformation-adequats/
content:
L&#8217;essor du numérique fait naître de nouvelles techniques de communication. Elles répondent aux objectifs en termes de notoriété et de visibilité d&#8217;une entreprise. Les réseaux ... <a title="Présence numérique sur les réseaux sociaux : les supports d&#8217;information adéquats" class="read-more" href="https://sametmax.com/presence-numerique-sur-les-reseaux-sociaux-les-supports-dinformation-adequats/" aria-label="Plus sur Présence numérique sur les réseaux sociaux : les supports d&#8217;information adéquats">Lire l'article</a>


feed_id: https://sametmax.com/?p=3623
title: Quel type de cadeau publicitaire intégrer dans votre campagne marketing ?
uri: Quel-type-de-cadeau-publicitaire-intégrer-dans-votre-campagne-marketi
url: https://sametmax.com/quel-type-de-cadeau-publicitaire-integrer-dans-votre-campagne-marketing/
content:
L&#8217;utilisation de cadeaux publicitaires dans les campagnes marketing est devenue une pratique courante et efficace. Ces objets, porteurs du logo ou des couleurs de l&#8217;entreprise, ... <a title="Quel type de cadeau publicitaire intégrer dans votre campagne marketing ?" class="read-more" href="https://sametmax.com/quel-type-de-cadeau-publicitaire-integrer-dans-votre-campagne-marketing/" aria-label="Plus sur Quel type de cadeau publicitaire intégrer dans votre campagne marketing ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3630
title: En quoi un QR code est-il utile pour votre entreprise ?
uri: En-quoi-un-QR-code-est-il-utile-pour-votre-entreprise
url: https://sametmax.com/en-quoi-un-qr-code-est-il-utile-pour-votre-entreprise/
content:
Né en 1994 grâce à l&#8217;entreprise japonaise Denso-Wave, le QR code s&#8217;est démocratisé au fil des années. Aujourd&#8217;hui, c&#8217;est une technologie à la portée de ... <a title="En quoi un QR code est-il utile pour votre entreprise ?" class="read-more" href="https://sametmax.com/en-quoi-un-qr-code-est-il-utile-pour-votre-entreprise/" aria-label="Plus sur En quoi un QR code est-il utile pour votre entreprise ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3590
title: Comment ouvrir compte bancaire en ligne sans justificatif ?
uri: Comment-ouvrir-compte-bancaire-en-ligne-sans-justificatif
url: https://sametmax.com/comment-ouvrir-compte-bancaire-en-ligne-sans-justificatif/
content:
De nos jours, l&#8217;accès aux services bancaires en ligne est devenu indispensable pour gérer ses finances facilement et rapidement. Dans cet article, nous abordons le ... <a title="Comment ouvrir compte bancaire en ligne sans justificatif ?" class="read-more" href="https://sametmax.com/comment-ouvrir-compte-bancaire-en-ligne-sans-justificatif/" aria-label="Plus sur Comment ouvrir compte bancaire en ligne sans justificatif ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3635
title: Nos conseils pour choisir le bon consultant Google Ads
uri: Nos-conseils-pour-choisir-le-bon-consultant-Google-Ads
url: https://sametmax.com/nos-conseils-pour-choisir-le-bon-consultant-google-ads/
content:
La sélection du bon consultant Google Ads est une décision cruciale. Elle influence la visibilité de votre entreprise en ligne et votre chiffre d&#8217;affaires. C&#8217;est ... <a title="Nos conseils pour choisir le bon consultant Google Ads" class="read-more" href="https://sametmax.com/nos-conseils-pour-choisir-le-bon-consultant-google-ads/" aria-label="Plus sur Nos conseils pour choisir le bon consultant Google Ads">Lire l'article</a>


feed_id: https://sametmax.com/?p=3593
title: Comment faire un bilan financier condensé ?
uri: Comment-faire-un-bilan-financier-condensé
url: https://sametmax.com/comment-faire-un-bilan-financier-condense/
content:
Dans le monde des affaires, il est essentiel de connaître l&#8217;état financier de son entreprise afin de prendre des décisions éclairées et d&#8217;assurer sa pérennité. ... <a title="Comment faire un bilan financier condensé ?" class="read-more" href="https://sametmax.com/comment-faire-un-bilan-financier-condense/" aria-label="Plus sur Comment faire un bilan financier condensé ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3640
title: BI : comment choisir les bons outils d’analyse de données ?
uri: BI-comment-choisir-les-bons-outils-d-analyse-de-données
url: https://sametmax.com/bi-comment-choisir-les-bons-outils-danalyse-de-donnees/
content:
L&#8217;utilisation croissante des logiciels de BI répond à l&#8217;augmentation de la quantité de données collectées par les entreprises. Ces outils permettent de générer de la ... <a title="BI : comment choisir les bons outils d&#8217;analyse de données ?" class="read-more" href="https://sametmax.com/bi-comment-choisir-les-bons-outils-danalyse-de-donnees/" aria-label="Plus sur BI : comment choisir les bons outils d&#8217;analyse de données ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3644
title: La gestion des systèmes de contrôle d’accès dans les hôtels à travers le M2M
uri: La-gestion-des-systèmes-de-contrôle-d-accès-dans-les-hôtels-à-t
url: https://sametmax.com/la-gestion-des-systemes-de-controle-dacces-dans-les-hotels-a-travers-le-m2m/
content:
Dans le secteur hôtelier, la gestion des systèmes de contrôle d&#8217;accès revêt une importance capitale pour assurer la sécurité et l&#8217;efficacité opérationnelle. L&#8217;avènement du M2M, ... <a title="La gestion des systèmes de contrôle d&#8217;accès dans les hôtels à travers le M2M" class="read-more" href="https://sametmax.com/la-gestion-des-systemes-de-controle-dacces-dans-les-hotels-a-travers-le-m2m/" aria-label="Plus sur La gestion des systèmes de contrôle d&#8217;accès dans les hôtels à travers le M2M">Lire l'article</a>


feed_id: https://sametmax.com/?p=3650
title: Les avantages d’une conférence en entreprise avec un sportif
uri: Les-avantages-d-une-conférence-en-entreprise-avec-un-sportif
url: https://sametmax.com/les-avantages-dune-conference-en-entreprise-avec-un-sportif/
content:
Organiser une conférence en entreprise avec un intervenant issu du monde sportif est une excellente manière de motiver et inspirer les collaborateurs. Ces conférences ont ... <a title="Les avantages d&#8217;une conférence en entreprise avec un sportif" class="read-more" href="https://sametmax.com/les-avantages-dune-conference-en-entreprise-avec-un-sportif/" aria-label="Plus sur Les avantages d&#8217;une conférence en entreprise avec un sportif">Lire l'article</a>


feed_id: https://sametmax.com/?p=3596
title: Quelle différence entre bilan financier et bilan fonctionnel ?
uri: Quelle-différence-entre-bilan-financier-et-bilan-fonctionnel
url: https://sametmax.com/quelle-difference-entre-bilan-financier-et-bilan-fonctionnel/
content:
Lorsqu&#8217;il s&#8217;agit de l&#8217;analyse financière d&#8217;une entreprise, deux instruments essentiels permettent d&#8217;évaluer sa santé financière&#160;: le bilan financier et le bilan fonctionnel. Cependant, il peut ... <a title="Quelle différence entre bilan financier et bilan fonctionnel ?" class="read-more" href="https://sametmax.com/quelle-difference-entre-bilan-financier-et-bilan-fonctionnel/" aria-label="Plus sur Quelle différence entre bilan financier et bilan fonctionnel ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3653
title: ChatGPT : comment l’utiliser pour la Data Analyse ?
uri: ChatGPT-comment-l-utiliser-pour-la-Data-Analyse
url: https://sametmax.com/chatgpt-comment-lutiliser-pour-la-data-analyse/
content:
ChatGPT est un outil de traitement automatique du langage naturel (TALN) développé par la société OpenAI. Il utilise des modèles d&#8217;intelligence artificielle (IA) avancés pour ... <a title="ChatGPT : comment l&#8217;utiliser pour la Data Analyse ?" class="read-more" href="https://sametmax.com/chatgpt-comment-lutiliser-pour-la-data-analyse/" aria-label="Plus sur ChatGPT : comment l&#8217;utiliser pour la Data Analyse ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3660
title: Choisir un partenaire d’affaires : comment faire le bon choix
uri: Choisir-un-partenaire-d-affaires-comment-faire-le-bon-choix
url: https://sametmax.com/choisir-un-partenaire-daffaires-comment-faire-le-bon-choix/
content:
Choisir un partenaire commercial est une décision cruciale qui peut avoir un impact significatif sur le succès de votre entreprise. Il s&#8217;agit de trouver quelqu&#8217;un ... <a title="Choisir un partenaire d’affaires : comment faire le bon choix" class="read-more" href="https://sametmax.com/choisir-un-partenaire-daffaires-comment-faire-le-bon-choix/" aria-label="Plus sur Choisir un partenaire d’affaires : comment faire le bon choix">Lire l'article</a>


feed_id: https://sametmax.com/?p=3663
title: Comment mettre en place la transformation numérique de votre site internet ?
uri: Comment-mettre-en-place-la-transformation-numérique-de-votre-site-int
url: https://sametmax.com/comment-mettre-en-place-la-transformation-numerique-de-votre-site-internet/
content:
La transformation digitale est devenue aujourd&#8217;hui une nécessité pour votre entreprise, et ce, peu importe sa taille. Elle inclut également la modernisation de votre site ... <a title="Comment mettre en place la transformation numérique de votre site internet ?" class="read-more" href="https://sametmax.com/comment-mettre-en-place-la-transformation-numerique-de-votre-site-internet/" aria-label="Plus sur Comment mettre en place la transformation numérique de votre site internet ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3598
title: Comment trouver un bilan financier ?
uri: Comment-trouver-un-bilan-financier
url: https://sametmax.com/comment-trouver-un-bilan-financier/
content:
Le bilan financier est un document essentiel pour analyser la situation financière d&#8217;une entreprise. Que vous soyez dirigeant, investisseur ou simple curieux, il peut s&#8217;avérer ... <a title="Comment trouver un bilan financier ?" class="read-more" href="https://sametmax.com/comment-trouver-un-bilan-financier/" aria-label="Plus sur Comment trouver un bilan financier ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3668
title: Optimiser vos campagnes Google Ads : trois conseils
uri: Optimiser-vos-campagnes-Google-Ads-trois-conseils
url: https://sametmax.com/optimiser-vos-campagnes-google-ads-trois-conseils/
content:
Une stratégie publicitaire réussie nécessite de l&#8217;expertise et du dévouement. Google Ads offre des opportunités exceptionnelles pour les annonceurs. C&#8217;est un outil puissant pour atteindre ... <a title="Optimiser vos campagnes Google Ads : trois conseils" class="read-more" href="https://sametmax.com/optimiser-vos-campagnes-google-ads-trois-conseils/" aria-label="Plus sur Optimiser vos campagnes Google Ads : trois conseils">Lire l'article</a>


feed_id: https://sametmax.com/?p=3600
title: Quelle différence entre swot et tows ?
uri: Quelle-différence-entre-swot-et-tows
url: https://sametmax.com/quelle-difference-entre-swot-et-tows/
content:
Le monde des affaires se caractérise par sa complexité et un environnement en perpétuel changement. Pour aider à naviguer dans cet environnement, plusieurs outils sont ... <a title="Quelle différence entre swot et tows ?" class="read-more" href="https://sametmax.com/quelle-difference-entre-swot-et-tows/" aria-label="Plus sur Quelle différence entre swot et tows ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3672
title: Comment apporter plus de personnalité à votre marque : 9 conseils essentiels
uri: Comment-apporter-plus-de-personnalité-à-votre-marque-9-conseils-es
url: https://sametmax.com/comment-apporter-plus-de-personnalite-a-votre-marque-9-conseils-essentiels/
content:
L&#8217;image de marque est essentielle pour toute entreprise. Elle représente l&#8217;identité et les valeurs de votre entreprise, et peut avoir un impact significatif sur la ... <a title="Comment apporter plus de personnalité à votre marque : 9 conseils essentiels" class="read-more" href="https://sametmax.com/comment-apporter-plus-de-personnalite-a-votre-marque-9-conseils-essentiels/" aria-label="Plus sur Comment apporter plus de personnalité à votre marque : 9 conseils essentiels">Lire l'article</a>


feed_id: https://sametmax.com/?p=3604
title: Comment faire un swot rh ?
uri: Comment-faire-un-swot-rh
url: https://sametmax.com/comment-faire-un-swot-rh/
content:
L&#8217;élaboration d&#8217;une stratégie de gestion des ressources humaines est essentielle pour le fonctionnement efficace et la croissance de toute entreprise. L&#8217;une des méthodes les plus ... <a title="Comment faire un swot rh ?" class="read-more" href="https://sametmax.com/comment-faire-un-swot-rh/" aria-label="Plus sur Comment faire un swot rh ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3679
title: Quelle importance revêt l’identité visuelle de votre marque ?
uri: Quelle-importance-revêt-l-identité-visuelle-de-votre-marque
url: https://sametmax.com/quelle-importance-revet-lidentite-visuelle-de-votre-marque/
content:
Dans un monde où l&#8217;attention des consommateurs est de plus en plus sollicitée, l&#8217;identité visuelle d&#8217;une marque revêt une importance capitale. Au-delà d&#8217;un simple ensemble ... <a title="Quelle importance revêt l&#8217;identité visuelle de votre marque ?" class="read-more" href="https://sametmax.com/quelle-importance-revet-lidentite-visuelle-de-votre-marque/" aria-label="Plus sur Quelle importance revêt l&#8217;identité visuelle de votre marque ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3607
title: Quel est l’intérêt de la matrice swot ?
uri: Quel-est-l-intérêt-de-la-matrice-swot
url: https://sametmax.com/quel-est-linteret-de-la-matrice-swot/
content:
Parfois appelée analyse décisionnelle, l&#8217;analyse SWOT est un outil incontournable dans le monde des affaires. Celle-ci permet aux entreprises d&#8217;évaluer leurs performances et de mettre ... <a title="Quel est l&#8217;intérêt de la matrice swot ?" class="read-more" href="https://sametmax.com/quel-est-linteret-de-la-matrice-swot/" aria-label="Plus sur Quel est l&#8217;intérêt de la matrice swot ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3609
title: Qu’est ce qu’une convention réglementée ?
uri: Qu-est-ce-qu-une-convention-réglementée
url: https://sametmax.com/quest-ce-quune-convention-reglementee/
content:
Dans le monde de l&#8217;entreprise et du droit, il existe un concept connu sous le nom de convention réglementée. Ce terme peut sembler obscur pour ... <a title="Qu&#8217;est ce qu&#8217;une convention réglementée ?" class="read-more" href="https://sametmax.com/quest-ce-quune-convention-reglementee/" aria-label="Plus sur Qu&#8217;est ce qu&#8217;une convention réglementée ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3690
title: Sécurité Entreprise Renforcée : La Puissance du SASE pour Contrer les Attaques de Phishing
uri: Sécurité-Entreprise-Renforcée-La-Puissance-du-SASE-pour-Contrer-l
url:
https://sametmax.com/securite-entreprise-renforcee-la-puissance-du-sase-pour-contrer-les-attaques-de-phishing/

content:
La sécurité des entreprises est une préoccupation majeure face aux attaques de phishing qui représentent une menace sérieuse pour les entreprises et qui sont de ... <a title="Sécurité Entreprise Renforcée : La Puissance du SASE pour Contrer les Attaques de Phishing" class="read-more" href="https://sametmax.com/securite-entreprise-renforcee-la-puissance-du-sase-pour-contrer-les-attaques-de-phishing/" aria-label="Plus sur Sécurité Entreprise Renforcée : La Puissance du SASE pour Contrer les Attaques de Phishing">Lire l'article</a>


feed_id: https://sametmax.com/?p=3683
title: La sécurité, au cœur des préoccupations de tout entrepreneur
uri: La-sécurité-au-cœur-des-préoccupations-de-tout-entrepreneur
url: https://sametmax.com/la-securite-au-coeur-des-preoccupations-de-tout-entrepreneur/
content:
La sécurité est un levier indispensable au développement des entreprises, quelle que soit leur taille. Une étude réalisée par l&#8217;INRS a révélé que 70 % ... <a title="La sécurité, au cœur des préoccupations de tout entrepreneur" class="read-more" href="https://sametmax.com/la-securite-au-coeur-des-preoccupations-de-tout-entrepreneur/" aria-label="Plus sur La sécurité, au cœur des préoccupations de tout entrepreneur">Lire l'article</a>


feed_id: https://sametmax.com/?p=3612
title: Où va l’argent d’une personne sous tutelle ?
uri: Où-va-l-argent-d-une-personne-sous-tutelle
url: https://sametmax.com/ou-va-largent-dune-personne-sous-tutelle/
content:
Dans notre société, nous rencontrons des situations dans lesquelles certaines personnes se trouvent dans l&#8217;incapacité de gérer leurs biens et leur argent. Dans ces circonstances, ... <a title="Où va l&#8217;argent d&#8217;une personne sous tutelle ?" class="read-more" href="https://sametmax.com/ou-va-largent-dune-personne-sous-tutelle/" aria-label="Plus sur Où va l&#8217;argent d&#8217;une personne sous tutelle ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3695
title: Les défis qu’auront à relever les designers UX/UI dans les prochaines années
uri: Les-défis-qu-auront-à-relever-les-designers-UX-UI-dans-les-prochai
url: https://sametmax.com/les-defis-quauront-a-relever-les-designers-ux-ui-dans-les-prochaines-annees/
content:
À l&#8217;ère de l&#8217;essor du numérique, les designers UX/UI jouent un rôle prépondérant dans l&#8217;optimisation des expériences en ligne. Les technologies sont en évolution constante ... <a title="Les défis qu&#8217;auront à relever les designers UX/UI dans les prochaines années" class="read-more" href="https://sametmax.com/les-defis-quauront-a-relever-les-designers-ux-ui-dans-les-prochaines-annees/" aria-label="Plus sur Les défis qu&#8217;auront à relever les designers UX/UI dans les prochaines années">Lire l'article</a>


feed_id: https://sametmax.com/?p=3700
title: Comment identifier le greenwashing dans les pratiques commerciales ?
uri: Comment-identifier-le-greenwashing-dans-les-pratiques-commerciales
url: https://sametmax.com/comment-identifier-le-greenwashing-dans-les-pratiques-commerciales/
content:
Le greenwashing est une tactique marketing progressivement répandue au sein des sociétés cherchant à se donner une image écoresponsable sans nécessairement adopter des gestes véritablement ... <a title="Comment identifier le greenwashing dans les pratiques commerciales ?" class="read-more" href="https://sametmax.com/comment-identifier-le-greenwashing-dans-les-pratiques-commerciales/" aria-label="Plus sur Comment identifier le greenwashing dans les pratiques commerciales ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3705
title: Comment comprendre et interpréter les résultats d’un audit de cybersécurité ?
uri: Comment-comprendre-et-interpréter-les-résultats-d-un-audit-de-cybe
url: https://sametmax.com/comment-comprendre-et-interpreter-les-resultats-dun-audit-de-cybersecurite/
content:
Dans le paysage numérique d&#8217;aujourd&#8217;hui, la cybersécurité est une préoccupation majeure pour toutes les entreprises, qu&#8217;elles soient grandes ou petites. Avec l&#8217;augmentation des menaces en ... <a title="Comment comprendre et interpréter les résultats d&#8217;un audit de cybersécurité ?" class="read-more" href="https://sametmax.com/comment-comprendre-et-interpreter-les-resultats-dun-audit-de-cybersecurite/" aria-label="Plus sur Comment comprendre et interpréter les résultats d&#8217;un audit de cybersécurité ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3710
title: Qu’attendre de votre agence web pour la création de votre site internet ?
uri: Qu-attendre-de-votre-agence-web-pour-la-création-de-votre-site-inte
url: https://sametmax.com/quattendre-de-votre-agence-web-pour-la-creation-de-votre-site-internet/
content:
Choisir un service spécialisé pour la création d&#8217;un site internet est une étape déterminante dans le développement de la présence en ligne d&#8217;une entreprise. Les ... <a title="Qu&#8217;attendre de votre agence web pour la création de votre site internet ?" class="read-more" href="https://sametmax.com/quattendre-de-votre-agence-web-pour-la-creation-de-votre-site-internet/" aria-label="Plus sur Qu&#8217;attendre de votre agence web pour la création de votre site internet ?">Lire l'article</a>


feed_id: https://sametmax.com/?p=3715
title: Pourquoi choisir des acteurs français pour sa cybersécurité ?
uri: Pourquoi-choisir-des-acteurs-français-pour-sa-cybersécurité
url: https://sametmax.com/pourquoi-choisir-des-acteurs-francais-pour-sa-cybersecurite/
content:
La cybersécurité est un enjeu majeur pour les entreprises, tant au niveau national qu&#8217;international. Dans ce contexte, il peut être intéressant de se tourner vers ... <a title="Pourquoi choisir des acteurs français pour sa cybersécurité ?" class="read-more" href="https://sametmax.com/pourquoi-choisir-des-acteurs-francais-pour-sa-cybersecurite/" aria-label="Plus sur Pourquoi choisir des acteurs français pour sa cybersécurité ?">Lire l'article</a>


