2012-10-19 12 views
5

ja dystrybucji pakiet, który ma taką strukturę:poprawny sposób na znalezienie katalogu skryptów z pliku setup.py w Python distutils?

mymodule: 
    mymodule/__init__.py 
    mymodule/code.py 
    scripts/script1.py 
    scripts/script2.py 

mymodule podkat od mymodule zawiera kod, a scripts podkat zawiera skrypty, które powinny być wykonywalny przez użytkownika.

Opisując instalacji pakietów w setup.py używam:

scripts=['myscripts/script1.py'] 

Aby określić, gdzie skrypty powinny iść. Podczas instalacji zwykle znajdują się w katalogu specyficznym dla platformy/użytkownika bin. Kod, który mam w mymodule/mymodule, wymaga jednak wywołania skryptów. Jaki jest właściwy sposób, aby znaleźć pełną ścieżkę do tych skryptów? Idealnie powinny one być na ścieżce użytkownika w tym momencie, więc jeśli chcę zadzwonić je z muszli, byłbym w stanie to zrobić:

os.system('script1.py args') 

Ale chcę wywołać skrypt o jego bezwzględnej ścieżki, a nie opierać się na platformie określonego katalogu bin jest na PATH, jak w:

# get the directory where the scripts reside in current installation 
scripts_dir = get_scripts_dir() 
script1_path = os.path.join(scripts_dir, "script1.py") 
os.system("%s args" %(script1_path)) 

jak można to zrobić? dzięki.

EDYCJA usunięcie kodu poza skryptem nie jest dla mnie rozwiązaniem praktycznym. Powodem jest to, że rozprowadzam zadania do systemu klastrów, a sposób w jaki zwykle to robię jest taki: wyobraź sobie, że masz zestaw zadań, które chcesz wykonywać. Mam skrypt, który przyjmuje wszystkie zadania jako dane wejściowe, a następnie wywołuje inny skrypt, który działa tylko w danym zadaniu. Coś jak:

main.py: 
for task in tasks: 
    cmd = "python script.py %s" %(task) 
    execute_on_system(cmd) 

tak main.py musi wiedzieć, gdzie script.py jest, ponieważ musi być wykonywalny polecenie przez execute_on_system.

+0

pokrewne: [określania lokalizacji danych distutils pliki programowo w Pythonie?] (Http://stackoverflow.com/q/8628495/95735) –

+0

Jak wygląda "execute_on_system()'? –

+0

@PiotrDobrogost: 'execute_on_system' przyjmuje jako wejście ciąg odpowiadający poleceniu powłoki. Następnie tworzy plik tymczasowy o nazwie 'cmd.sh' i wstawia do niego polecenie wraz z niezbędnymi prefiksami określającymi sposób uruchomienia zadania (specyficzne dla systemu klastrowego używanego w systemie użytkownika) - np. Co kolejka do pracy powinien wejść, itd. Następnie wykonuje ten skrypt, 'cmd.sh' i wykonuje go w sposób specyficzny dla systemu, np przez wykonanie: 'os.system (" qsub cmd.sh ")' – user248237dfsf

Odpowiedz

3

Myślę, że powinieneś ustrukturyzować swój kod, aby nie trzeba było wywoływać skryptów z twojego kodu. Przenieś potrzebny kod ze skryptów do pakietu, a następnie możesz wywołać ten kod zarówno ze skryptów, jak iz kodu.

+0

Podoba mi się ten pomysł, ale w praktyce to nie działa dla mnie zobacz nadchodzącą edycję – user248237dfsf

+0

Nic nie widzę w twoim przepływie pracy uniemożliwiającym przeniesienie kodu ze skryptu do paczki –

+0

Potrzebuję być w stanie wykonać polecenie, które wywołuje skrypt Python, który jest częścią mojego pakietu.Coś jak "python myscript.py someargs" .Dlatego potrzebuję wiedzieć * gdzie * myscript.py żyje ... Nawet myscript.py był częścią pakietu, a nie w katalogu skryptów, nadal musiałbym używać hacka jak '__file__', aby dowiedzieć się, gdzie znajduje się skrypt. które są lepsze od projektu raczej niż próbować dowiedzieć się, gdzie znajduje się katalog skryptów? Oba rozwiązania wydają się nieeleganckie. – user248237dfsf

1

Moim przypadkiem użycia było sprawdzenie, czy katalog, w którym są zainstalowane moje skrypty, znajduje się na ścieżce użytkownika i ostrzega, jeśli nie (ponieważ często nie znajduje się na ścieżce, jeśli instaluje się z --user). Oto rozwiązanie, które wymyśliłem:

from setuptools.command.easy_install import easy_install 

class my_easy_install(easy_install): 

    # Match the call signature of the easy_install version. 
    def write_script(self, script_name, contents, mode="t", *ignored): 

     # Run the normal version 
     easy_install.write_script(self, script_name, contents, mode, *ignored) 

     # Save the script install directory in the distribution object. 
     # This is the same thing that is returned by the setup function. 
     self.distribution.script_install_dir = self.script_dir 

... 

dist = setup(..., 
      cmdclass = {'build_ext': my_builder, # I also have one of these. 
         'easy_install': my_easy_install, 
         }, 
      ) 

if dist.script_install_dir not in os.environ['PATH'].split(':'): 
    # Give a sensible warning message... 

Chciałbym podkreślić, że jest to dla setuptools. Jeśli używasz distutils, to rozwiązanie jest podobne, ale nieco inaczej:

from distutils.command.install_scripts import install_scripts 

class my_install_scripts(install_scripts): # For distutils 
    def run(self): 
     install_scripts.run(self) 
     self.distribution.script_install_dir = self.install_dir 

dist = setup(..., 
      cmdclass = {'build_ext': my_builder, 
         'install_scripts': my_install_scripts, 
         }, 
      )