Выполнить скрипт Python с тем же именем в другом каталоге - PullRequest
0 голосов
/ 24 сентября 2018

У меня следующая файловая структура:

A:

| _ a.py

| _ b.py

B:

| _ a.py

| _ b.py

Я хочу динамически выполнить A / b.py или B / b.py.

Я использую следующий код:

from importlib import import_module    
    path = '/home/username/test/' + module + '/'
    if path not in sys.path:
        sys.path.append(path)
    script = import_module('b', 'Script')
    myClass = getattr(script, 'Script')
    run = myClass()

При этом, если я запустил B / b.py, а затем A / b.py, он выполнит B / b.py вместо A / b.py.

Первый скрипт, который будет запущен, будет выполнен в следующем раунде.

Мне нужна помощь, чтобы убедиться, что файл в каталоге, который я хочу, запускается только.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Я прочитал ваш другой, похожий вопрос и нашел решение без какого-либо предварительного импорта.Это (imho) крайне непитоническое и может во что бы то ни стало считаться грязным "хаком".Я настоятельно рекомендую вам рассмотреть мой другой ответ и просто правильно разобраться с импортом.

Ваша проблема возникает из-за того, что вы уничтожаете пространство имен и все, что ему дорого.Когда вы загрязняете пространство имен функциями / методами с одинаковой сигнатурой, Python-интерпретатор абсолютно не может их различить: он разрешается тем, который был впервые импортирован.

Однако, как уже было сказано,это обходной путь: (в настоящее время) нет способа выгрузить модуль python, но вы можете reload его использовать, используя модуль imp.По сути, это позволяет вам очистить (переопределить) пространство имен.Полный рабочий пример можно найти на моем repl.it

# root_folder/main.py
import sys
import imp
from importlib import import_module


def import_script(mod_dir, script):
  sys.path.append(mod_dir)
  mod = imp.reload(import_module(script, 'Script'))
  sys.path.remove(mod_dir)
  return mod

# input:
mod_dir = "A"
script = "b"

# import module/script.py
active_mod = import_script(mod_dir, script)

# use module/script.py
mod_name = active_mod.get_mod_name()
print(mod_name) # Prints "A : b.y"


# New input: different module/script.py
mod_dir = "C"
script = "b"

# import module/script.py
active_mod = import_script(mod_dir, script)

# use module/script.py
mod_name = active_mod.get_mod_name()
print(mod_name) # Prints "C : b.y"

, когда модули выглядят как показано ниже:

# root_folder/A/b.py
def get_mod_name():
  return "A : b.py"

Обратите внимание, что каждый импортв два раза, поскольку каждый раз, когда вы импортируете модуль (возможно, с дублированным именем), его также необходимо перезагружать для очистки пространства имен.Недостаточно просто del модуля.

0 голосов
/ 24 сентября 2018

Я делаю некоторые предположения о том, что вы хотите сделать здесь.Даже если это не совсем то, что вам нужно, это все равно может подтолкнуть вас в правильном направлении: у вас есть два разных подкаталога, A и B .Они содержат сценарии с одинаковыми именами a.py и b.py .Исходя из некоторых условий, ваш скрипт должен вызвать либо A / a.py или A / a.py , а затем, возможно, B / b.py или B / b.py .

Я бы настроил A и B как настоящие модули python, то есть создайте файл __ init __. Py в обеих папках.Затем есть мастер-скрипт, который каким-то образом определяет, какой модуль использовать ..

# root_folder/master.py
import sys
import A
import B

master_script_name = sys.argv[0]

print("I'm the master script : " + str(master_script_name))


def choose_module_A_or_B(arg):
  if arg == "A":
    print(" You chose module A !")
    return A
  return B


module = choose_module_A_or_B("A")

module.b.print_locations()

Затем

# root_folder/A/__init__.py
from A import b

и

# root_folder/A/b.py
import os
import sys

# how to obtain paths and script name:
folder = os.path.dirname(os.path.realpath(__file__))
script = __file__
parent = os.path.abspath(os.path.join(folder, os.pardir))

def print_locations():
  print(" --> script : " + str(script))
  print(" --> folder : " + str(folder))
  print(" --> parent : " + str(parent))

Аналогично ..

# root_folder/B/__init__.py
from B import b

и,

# root_folder/B/b.py
import os
import sys

# how to obtain paths and script name:
folder = os.path.dirname(os.path.realpath(__file__))
script = __file__
parent = os.path.abspath(os.path.join(folder, os.pardir))

def print_locations():
  print(" --> script : " + str(script))
  print(" --> folder : " + str(folder))
  print(" --> parent : " + str(parent))

ВЫХОД:

$ python master.py
I'm the master script : master.py
You chose module A !
--> script : A\b.py
--> folder : C:\dev\ScriptTesting\py\script_by_name\A
--> parent : C:\dev\ScriptTesting\py\script_by_name
...