如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?
Posted
技术标签:
【中文标题】如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?【英文标题】:How to run python scripts in another directory, without writing scripts to disk? 【发布时间】:2021-04-18 01:56:29 【问题描述】:假设我有两个 python 脚本 methods.py
和 driver.py
。
methods.py
定义了所有方法,driver.py
在我运行它时完成了所需的工作。
假设我在包含两个文件driver.py
和methods.py
的主目录中,并且我在主目录中有n
子目录,名为subdir1
,subdir2
,...,subdirn
.所有这些子目录都有作为driver.py
输入的文件。
我要做的是在所有这些子目录中运行 driver.py
并从中获取我的输出,而不将 driver.py
写入磁盘。
我应该怎么做? 目前,我正在使用 subprocess 模块来
-
将 driver.py 和 methods.py 复制到子目录中。
运行它们。
复制部分很简单:
import subprocess
for i in range(n):
cmd = "cp methods.py driver.py subdir"+str(i)
p = subprocess.Popen(cmd, shell=True)
p.wait()
#once every subdirectory has driver.py and methods.py, start running these codes
for i in range(n):
cmd = "cd subdir" + str(i) +" && python driver.py"
p = subprocess.Popen(cmd, shell=True)
p.wait()
有没有办法在不占用磁盘空间的情况下完成上述操作?
【问题讨论】:
为什么不修改 driver.py 以接受目录路径?这样,您可以遍历子目录并执行python driver.py /path/to/subdiri
。您可能还需要确保 driver.py 代码可以在任何输入目录中运行。
@GinoMempin,哦让它接受整个目录作为输入?我实际上并没有做过这样的事情,但我可以找到一些东西来学习如何做到这一点。谢谢!
【参考方案1】:
扩展my initial comment,而不是到处复制driver.py,你可以让它接受一个子目录的路径作为命令行参数。然后,您还必须确保它可以从任何目录执行它应该执行的任何操作。这意味着要考虑文件的正确路径。
有多种方法可以接受命令行参数(请参阅How to read/process command line arguments?)。为简单起见,我们只使用sys.args
来获取路径。
这是一个修改后的 driver.py
import sys
from pathlib import Path
# Receive the path to the target subdir as command line args
try:
subdir_path = Path(sys.argv[1]).resolve()
except Exception as e:
print('ERROR resolving path to subdir')
print(e)
sys.exit(1)
# Do stuff, taking into account full path to subdir
print(f'Running driver on subdir_path')
with open(subdir_path.joinpath('input.txt'), 'r') as f:
data = f.read()
print(f'Got data = data')
假设在获取路径后,driver.py 期望从每个子目录中读取一个文件 (input.txt)。所以在这里你需要获取子目录的绝对路径 (.resolve()
) 并在访问 input.txt (.joinpath()
) 时使用它。基本上,认为 driver.py 将始终从 main 目录运行。
示例用法如下:
main$ tree
.
├── driver.py
├── method.py
├── subdir1
│ └── input.txt
├── subdir2
│ └── input.txt
└── subdir3
└── input.txt
main$ python driver.py /temp/main/subdir3
Running driver on /temp/main/subdir3
Got data = 3333
现在,在 method.py 中,您不需要“复制 driver.py”代码。只需遍历 main 下的所有 subdirn 文件夹,然后将完整路径传递给 driver.py。您仍然可以使用相同的 Popen(...)
代码调用 driver.py。
这是一个修改后的method.py:
import subprocess
from pathlib import Path
# Assume all subdirs are under the current directory
parent_path = Path.cwd()
for child_path in parent_path.iterdir():
# Skip files/folders not named 'subdirn'
if not child_path.is_dir() or 'subdir' not in child_path.stem:
continue
# iterdir returns full paths (cwd + /subdir)
print(f'Calling driver.py on child_path')
cmd = f'python driver.py child_path'
p = subprocess.Popen(cmd, shell=True)
p.wait()
示例运行:
main$ python method.py
Calling driver.py on /temp/main/subdir3
Running driver on /temp/main/subdir3
Got data = 3333
Calling driver.py on /temp/main/subdir2
Running driver on /temp/main/subdir2
Got data = 2222
Calling driver.py on /temp/main/subdir1
Running driver on /temp/main/subdir1
Got data = 1111
还要注意所有的执行都是从 main 完成的。
一些注意事项:
您可以使用iterdir
或其等效的os.listdir
来获取基本路径下的所有文件/文件夹,而不是硬编码range(n)
,这应该可以方便地返回绝对路径。除非您需要按特定顺序浏览子目录。
我更喜欢使用pathlib
而不是os.path
,因为它为文件/文件夹路径提供了更多高级抽象。如果你想或需要使用os.path
,有这个table of os.path - pathlib equivalents。
我在这里使用了 f 字符串(参见 What is print(f"...")),它仅适用于 Python 3.6+。如果您使用的是较低版本,只需替换为任何其他字符串格式化方法即可。
【讨论】:
【参考方案2】:你可以使用 python 的 os.chdir() 函数来改变当前的工作目录:
import os
#import methods
root = os.getcwd()
for d in ['subdir1', 'subdir2']:
os.chdir(os.path.join(root, d))
print("dir:", os.getcwd())
exec(open("../driver.py").read())
我也不确定你是否需要 popen,因为 python 能够使用 exec 函数执行 python 文件。在这种情况下,这取决于您如何导入 methods.py。您是简单地导入它还是在 driver.py 中以其他方式使用它? 您可以尝试在主脚本内的顶层导入它或使用扩展路径,例如:
exec(open("../methods.py").read())
在您的驱动程序脚本中。请记住,这些解决方案都不是很优雅。最好按照 Gino Mempin 的建议处理您的 driver.py 内部的路径。你可以从那里调用 os.chdir()。
【讨论】:
感谢您的回答@areop-enap!我只导入methods.py。 os,chdir(os.path.join(root, d)) 是否将我的目录更改为 subdir1,并 exec(open(...).read()) 运行 driver.py INSIDE subdir1? 是的,我使用仅包含函数调用 open('test.txt','wt').write('test') 的 test.py 对其进行了测试,以确保它正常工作。这样做的问题是:您需要以某种方式包含methods.py,并且由于您将工作目录更改为您的子文件夹,因此您无法通过简单的导入来访问它。您必须先执行 sys.path.append("[absolute path to method.py]"),然后再执行 driver.py 的“导入方法”内幕。您可以在执行 driver.py 之前尝试导入它,但我不确定这是否有效。您的 methods.py 需要以某种方式支持它。以上是关于如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?的主要内容,如果未能解决你的问题,请参考以下文章