I'm trying to make my modules available globally
Filesystem structure
main.py
module_static.py
folder/module_dynamic.py # this is example, but imagine 100s of modules
main.py
print('Loading module_static')
import module_static
module_static.test()
# Trying to make module_static available globally
globals()['module_static'] = module_static
__all__ = ['module_static']
print('Loading module_dynamic')
import sys
sys.path.append('./folder/')
import module_dynamic
module_dynamic.test()
module_static.py
def test():
print(' -> This is module_static')
module_dynamic.py
def test():
print(' -> This is module_dynamic')
module_static.test()
Running main.py creates the following execution flow main.py -> module_dynamic.py -> module_static.py
So as you can see:
Loading of modules is working properly
However, despite trying to make module_static available globally, it isn't working a module_dynamic.py throws an error saying module_static doesn't exist
How can I make module_static.py available in module_dynamic.py (ideally without having to write any additional code in module_dynamic.py)?
Not saying it's good practice, but you can do
main.py
import builtins
import module_static
builtins.module_static = module_static
This should allow you to use module_static from anywhere.
More info on builtins: How to make a cross-module variable?
It can't work the way you expect. globals() return a dict of globals variables in your script. Maybe this may help you to understand
You can take a look at this course for better understanding
https://www.python-course.eu/python3_global_vs_local_variables.php
Anyway, you will have to import the module to use it.
If it's just a local tool for your personnal use, you could move it to the folder
{Python_installation_folder}/Lib.
Then, in any script, you will be able to do
import module_static
and use your module.
If you want to share your module with other people, publish (upload) it on PyPi. You could follow the tutorial bellow
https://anweshadas.in/how-to-upload-a-package-in-pypi-using-twine/
Related
I have a file called dns_poison.py that needs to call a package called netscanner. When i try and load the icmpscan module from dns_poison.py I get this message:
ModuleNotFoundError: No module named 'icmpscan'
I've done a sys.path and can confirm that the correct path is in place. The files are located at D:\PythonProjects\Networking\tools and D:\PythonProjects appears when I do a sys.path.
Here is my directory structure:
dns_poison.py
netscanner/
__init__.py
icmpscan.py
Code snippets for the files are as follows:
dns_poison.py
import netscanner
netscanner\__init__.py
from icmpscan import ICMPScan
netscanner\icmpscan.py
class ICMPScan:
def __init__(self, target, count=2, timeout=1):
self.target = target
self.count = count
self.timeout = timeout
self.active_hosts = []
# further code below here....
I don't understand why it cannot find the module, as I've used this exact same method on other python projects without any problems. Any help would be much appreciated.
When you run python dns_poison.py, the importer checks the module path then the local directory and eventually finds your netscanner package that has the following available:
netscanner
netscanner.icmpscan
netscanner.icmpscan.ICMPScan
Now I ask you, where is just icmpscan? The importer cannot find because well, it doesnt exist. The PYTHONPATH exists at wherever dns_poison.py resides, and doesn't append itself to include the absolute path of any imported modules because that simply not how it works. So netscanner can be found because its at the same level as dns_poison.py, but the importer has no clue where icmpscan.py exists because you havent told it. So you have two options to alter your __init__.py:
from .icmpscan import ICMPScan which works with Python 3.x
from netscanner.icmpscan import ICMPScan which works with both Python 2.x/3.x
Couple of references for you:
Python Import System
Python Modules recommend you ref section 6.4.2 Intra-package References
The most simple way to think about this is imports should be handled relative to the program entry-point file. Personally I find this the most simple and fool-proof way of handling import paths.
In your example, I would have:
from netscanner.icmpscan import ICMPScan
In the main file, rather than add it to init.py.
I've read through about ten posts on how to import local modules, and I'm still stumped on why this isn't working. I have an extremely simple module, actor.py, with a single class inside it:
class Actor(object):
def __init__(self, name, age):
self.name = name
self.age = age
I'm trying to import it into another module, scraper.py, within the same directory:
Some fixes have listed not having init.py as being a problem with local imports, so I know that's not my problem.
Initially I tried these:
import actor
and
from actor import Actor
but it tells me that actor and Actor are unresolved references. here tells me that's Python 2 syntax, and I'm using Python 3. That answer instead recommends that I do:
from .actor import Actor
When I run my program with that syntax, I get this error:
ModuleNotFoundError: No module named '__main__.actor'; '__main__' is not a package
So I go searching again, and this post tells me to remove the dot from 'actor,' but as stated before, I've tried that as well. My final guess was
from . import actor
but that yields
ImportError: cannot import name 'actor'
which I follow to here, but the answers there mention circular dependencies, and I'm certain actor and scraper have none. Am I perhaps not writing my module correctly? I can't think of any other ways to write an import statement.
edit: if it helps at all, I'm using Intellij
Try from WebScraper.actor import Actor. If this doesn't work its because your package directory is not in the PYTHONPATH. You can set that in the IntelliJ Python run configuration.
The relative import is not working for you because you are trying to run a module as a script. You can see an explanation of what is happening at https://stackoverflow.com/a/8300343/7088038. If you want relative imports to work you will have to add a __main__.py file to your module to allow it to be runnable, or execute from an external script where you use an absolute import so you don't clobber the package namespace.
One other stylistic note- usually (but not always) package names in python use all lowercase names. CamelCase is reserved for class names. So if you wanted to follow convention you would call your package webscraper and use from webscraper.actor import Actor
To import a class into your script use:
from actor import Actor
Or to import the .py entirely (including whatever imports included in it) into the namespace use:
from actor import *
I have a module that wraps another module to insert some shim logic in some functions. The wrapped module uses a settings module mod.settings which I want to expose, but I don't want the users to import it from there, in case I would like to shim something there as well in the future. I want them to import wrapmod.settings.
Importing the module and exporting it works, but is a bit verbose on the client side. It results in having to write settings.thing instead of just thing.
I want the users to be able to do from wrapmod.settings import * and get the same results as if they did from mod.settings import * but right now, only from wrapmod import settings is available. How to I work around this?
If I understand the situation correctly, you're writing a module wrapmod that is intended to transform parts of an existing package mod. The specific part you're transforming is the submodule mod.settings. You've imported the settings module and made your changes to it, but even though it is available as wrapmod.settings, you can't use that module name in an from ... import ... statement.
I think the best way to fix that is to insert the modified module into sys.modules under the new dotted name. This makes Python accept that name as valid even though wrapmod isn't really a package.
So wrapmod would look something like:
import sys
from mod import settings
# modify settings here
sys.modules['wrapmod.settings'] = settings # add this line!
I ended up making a code-generator for a thin wrapper module instead, since the sys.module hacking broke all IDE integration.
from ... import mod
# this is just a pass-through wrapper around mod.settings
__all__ = mod.__all__
# generate pass-through wrapper around mod.settings; doesn't break IDE integration, unlike manual sys.modules editing.
if __name__ == "__main__":
for thing in settings.__all__:
print(thing + " = mod." + thing)
which when run as a script, outputs code that can then be appended to the end of this file.
i need to call a function from from one python class to another which are at different directories.
I'm using Eclipse and PyDev for developing scripts.
sample.py
class Employee:
def meth1(self,arg):
self.arg=arg
print(arg)
ob=Employee()
ob.meth1("world")
main.py
class main:
def meth(self,arg):
self.arg=arg
print(arg)
obj1=main()
obj1.meth("hello")
I need to access meth1 in main.py
updated code
main.py
from samp.sample import Employee
class main:
def meth(self,arg):
self.arg=arg
print(arg)
obj1=main()
obj1.meth("hello")
After executing main.py it is printing "world" automatically without calling it.
my requirement is i need to call meth1 from main.py explicitly
please find my folder below
import is the concept you need here. main.py will need to import sample and then access symbols defined in that module such as sample.Employee
To ensure that sample.py can be found at import time, the path to its parent directory can be appended to sys.path (to get access to that, of course, you will first need to import sys). To manipulate paths (for example, to turn a relative path like '../samp' into an absolute path, you might want to import os as well and take a look at the standard library functions the sub-module os.path has to offer.
You will have to import the sample.py file as a module to your main.py file. Since the files are in different directories, you will need to use the __init__.py
From the documentation:
The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.
Here is a related stack overflow question which explains the solution in more detail.
It's generally not a good idea to alter the sys.path variable. This can make scripts non-portable. Better is to just place your extra modules in the user site directory. You can find out what that is with the following script.
import os
import sys
import site
print(os.path.join(site.USER_BASE, "lib", "python{}.{}".format(*sys.version_info[0:2]), "site-packages"))
Place your modules there. Then you can just import as any other module.
import sample
emp = sample.Employee()
Later you can package it using distutils or setuptools and the imports will still work the same.
I understand how to actually link python files, however, i don't understand how to get variable's from these linked files. I've tried to grab them and I keep getting NameError.
How do I go about doing this? The reason i want to link files is to simply neaten up my script and not make it 10000000000 lines long. Also, in the imported python script, do i have to import everything again? Another question, do i use the self function when using another scripts functions?
ie;
Main Script:
import sys, os
import importedpyfile
Imported Py File
import sys, os
I understand how to actually link python files, however, i don't
understand how to get variable's from these linked files. I've tried
to grab them and I keep getting NameError.
How are you doing that? Post more code. For instance, the following works:
file1.py
#!/usr/bin/env python
from file2 import file2_func, file2_variable
file2_func()
print file2_variable
file2.py:
#!/usr/bin/env python
file2_variable = "I'm a variable!"
def file2_func():
print "Hello World!"
Also, in the imported python script, do i have to import everything
again?
Nope, modules should be imported when the python interpreter reads that file.
Another question, do i use the self function when using another
scripts functions?
Nope, that's usually to access class members. See python self explained.
There is also more than one way to import files. See the other answer for some explanations.
I think what you are trying to ask is how to get access to global vars from on .py file without having to deal with namespaces.
In your main script, replace the call to import importedpyfile to say this instead
from importedpyfile import *
Ideally, you keep the code the way you have it. But instead, just reference those global vars with the importedpyfile namespace.
e.g.
import importedpyfile
importedpyfile.MyFunction() # calls "MyFunction" that is defined in importedpyfile.py
Python modules are not "linked" in the sense of C/C++ linking libraries into an executable. A Python import operation creates a name that refers to the imported module; without this name there is no (direct) way to access another module.