2015-11-18 1 views
1

Quel appel système os.listdir exécute-t-il en interne et y a-t-il une possibilité de suspension de processus Python en raison d'un scénario où os.listdir est sur un lecteur réseau monté?Est-ce que os.listdir peut se bloquer avec les lecteurs réseau? Quel appel système utilise-t-il?

Nous suspectons un problème sur notre serveur d'application à cause de os.listdir qui essaie de lister un partage samba monté sur une machine linux. Apparemment, le DNS de la part de samba avait changé au moment où nous avons eu ce problème. Nous essayons toujours de reproduire ce scénario, mais quelqu'un peut-il me dire comment cela fonctionnerait? Et aussi des commandes comme ls pendre aussi comme ça?

Existe-t-il des moyens de gérer cela à l'espace utilisateur?

Répondre

4

Le CPY implementation of os.listdir de CPython utilise des appels de bibliothèque C spécifiques à la plate-forme pour lire le contenu d'un répertoire. Sur les plates-formes de type Unix, ce sont opendir(3) et readdir(3), et Windows utilise FindFirstFile et FindNextFile.

Le comportement de ces appels en présence de systèmes de fichiers réseau inaccessibles dépend du système d'exploitation. Lorsque vous utilisez Linux ou Windows, ils sont certains de se bloquer dans les situations dans lesquelles les commandes système telles que ls se bloquer. Pour éviter des pauses arbitrairement longues, on peut utiliser des frameworks spécialisés, tels que asyncio et twisted qui utilisent des E/S non bloquantes. L'utilisation de ces frameworks peut cependant être décourageante, et nécessite généralement de les utiliser tout au long de l'application et du programme entier dans un modèle piloté par les événements.

Une méthode plus simple et plus adaptée aux débutants pour s'assurer que les appels système IO ne bloquent pas en présence de systèmes de fichiers réseau consiste à utiliser des threads. À titre d'exemple, voici une fonction safe_listdir qui retourne le contenu du répertoire ou None si l'appel a pris plus d'un délai spécifié:

import os, threading 

def safe_listdir(directory, timeout): 
    contents = [] 
    t = threading.Thread(target=lambda: contents.extend(os.listdir(directory))) 
    t.daemon = True # don't delay program's exit 
    t.start() 
    t.join(timeout) 
    if t.is_alive(): 
     return None 
    return contents 
+0

Y at-il une façon que nous pouvons gérer ces choses sans modifier la mise en œuvre du noyau? Quelque chose comme un temps mort aurait-il un sens? – Nishant

+0

Brillant, je n'ai pas beaucoup utilisé les fils. Mais c'est un bon exemple pour apprendre ces concepts. Va passer par l'exemple. Son quelque chose comme séparer le "contrôle de la connectivité réseau" du vrai Python ou quelque chose dans ce sens. – Nishant

+1

@Nishant Editer la réponse pour supprimer la gestion "morte". Il s'avère que les threads Python n'ont pas besoin d'être "joints" avec succès pour se nettoyer après eux-mêmes. – user4815162342